Merge remote-tracking branch 'origin/master' into reproj-ident

This commit is contained in:
Matthew Perry 2016-06-03 06:21:37 -04:00
commit a5f4bdd96a
54 changed files with 363 additions and 352 deletions

10
CITATION.txt Normal file
View File

@ -0,0 +1,10 @@
If you use Rasterio for any published work, please cite it using the reference
below:
@Misc{,
author = {Sean Gillies and others},
organization = {Mapbox},
title = {Rasterio: geospatial raster I/O for {Python} programmers},
year = {2013--},
url = "https://github.com/mapbox/rasterio"
}

View File

@ -74,8 +74,7 @@ Cython language is a superset of Python. Cython files end with ``.pyx`` and
``.pxd`` and are where we keep all the code that calls GDAL's C functions.
Rasterio supports Python 2 and Python 3 in the same code base, which is
aided by an internal compatibility module named ``five.py``. Renaming it is a
to-do (`#719 <https://github.com/mapbox/rasterio/issues/719>`__). It functions
aided by an internal compatibility module named ``compat.py``. It functions
similarly to the more widely known `six <https://pythonhosted.org/six/>`__ but
we only use a small portion of the features so it eliminates a dependency.

View File

@ -217,7 +217,7 @@ pseudoxml:
.PHONY: apidocs
apidocs:
sphinx-apidoc -f -e -T -M -o . ../rasterio ../rasterio/rio ../rasterio/five.py ../rasterio/tools ../rasterio/tool.py
sphinx-apidoc -f -e -T -M -o . ../rasterio ../rasterio/rio ../rasterio/compat.py ../rasterio/tools ../rasterio/tool.py
.PHONY: publish
publish: html

View File

@ -50,7 +50,7 @@ to bands using the ``write_colormap()`` method.
import rasterio
with rasterio.drivers():
with rasterio.Env():
with rasterio.open('tests/data/shade.tif') as src:
shade = src.read(1)

View File

@ -61,7 +61,7 @@ Here is the program in examples/concurrent-cpu-bound.py.
def main(infile, outfile, num_workers=4):
with rasterio.drivers():
with rasterio.Env():
# Open the source dataset.
with rasterio.open(infile) as src:

View File

@ -68,7 +68,7 @@ Rasterio
The object returned when you call ``rasterio.Env()`` is a context manager. It
handles the GDAL configuration for a specific block of code and resets the
configuration when the block exits for any reason, success or failure. The
Rasterio ``with Env()`` pattern organizes GDAL configuration into single
Rasterio ``with rasterio.Env()`` pattern organizes GDAL configuration into single
statements and makes its relationship to a block of code clear.
If you want to know what options are configured at any time, you could bind it

View File

@ -14,14 +14,14 @@ GDAL options are typically set as environment variables. While
environment variables will influence the behavior of ``rasterio``, we
highly recommended avoiding them in favor of defining behavior programatically.
The preferred way to set options for rasterio is via ``rasterio.drivers()``.
The preferred way to set options for rasterio is via ``rasterio.Env()``.
Options set on entering the context are deleted on exit.
.. code-block:: python
import rasterio
with rasterio.drivers(GDAL_TIFF_INTERNAL_MASK=True):
with rasterio.Env(GDAL_TIFF_INTERNAL_MASK=True):
# GeoTIFFs written here will have internal masks, not the
# .msk sidecars.
...

View File

@ -26,7 +26,7 @@ This is best illustrated by example. Opening a raster file with ``osgeo.gdal``
Compared to the similar code in ``rasterio``::
import rasterio
with rasterio.drivers():
with rasterio.Env():
with rasterio.open(filename, 'r') as dataset:
# ... work with dataset

View File

@ -10,7 +10,7 @@ out = '/tmp/reproj.tif'
dst_crs = crs.from_string("EPSG:3759")
with rasterio.drivers(CHECK_WITH_INVERT_PROJ=True):
with rasterio.Env(CHECK_WITH_INVERT_PROJ=True):
with rasterio.open(rgb) as src:
profile = src.profile

View File

@ -23,7 +23,7 @@ transform.
from rasterio import Affine as A
from rasterio.warp import reproject, RESAMPLING
with rasterio.drivers():
with rasterio.Env():
# As source: a 512 x 512 raster centered on 0 degrees E and 0
# degrees N, each pixel covering 15".

View File

@ -25,7 +25,7 @@ An array is written to a new single band TIFF.
# Register GDAL format drivers and configuration options with a
# context manager.
with rasterio.drivers():
with rasterio.Env():
# Write the product as a raster band to a new 8-bit file. For
# the new file's profile, we start with the meta attributes of
@ -40,7 +40,7 @@ An array is written to a new single band TIFF.
with rasterio.open('example-total.tif', 'w', **profile) as dst:
dst.write(array.astype(rasterio.uint8), 1)
# At the end of the ``with rasterio.drivers()`` block, context
# At the end of the ``with rasterio.Env()`` block, context
# manager exits and all drivers are de-registered.
Writing data mostly works as with a Python file. There are a few format-

View File

@ -16,8 +16,8 @@ import rasterio
from rasterio._example import compute
def main(infile, outfile, with_threads=False):
with rasterio.drivers():
with rasterio.Env():
# Open the source dataset.
with rasterio.open(infile) as src:
@ -33,7 +33,7 @@ def main(infile, outfile, with_threads=False):
with rasterio.open(outfile, 'w', **meta) as dst:
loop = asyncio.get_event_loop()
# With the exception of the ``yield from`` statement,
# process_window() looks like callback-free synchronous
# code. With a coroutine, we can keep the read, compute,
@ -46,10 +46,10 @@ def main(infile, outfile, with_threads=False):
@asyncio.coroutine
def process_window(window):
# Read a window of data.
data = src.read(window=window)
# We run the raster computation in a separate thread
# and pause until the computation finishes, letting
# other coroutines advance.
@ -63,13 +63,13 @@ def main(infile, outfile, with_threads=False):
None, compute, data, result)
else:
compute(data, result)
dst.write(result, window=window)
# Queue up the loop's tasks.
tasks = [asyncio.Task(process_window(window))
tasks = [asyncio.Task(process_window(window))
for ij, window in dst.block_windows(1)]
# Wait for all the tasks to finish, and close.
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
@ -93,6 +93,6 @@ if __name__ == '__main__':
action='store_true',
help="Run with a pool of worker threads")
args = parser.parse_args()
main(args.input, args.output, args.with_workers)

View File

@ -2,14 +2,14 @@
Operate on a raster dataset window-by-window using a ThreadPoolExecutor.
Simulates a CPU-bound thread situation where multiple threads can improve performance.
Simulates a CPU-bound thread situation where multiple threads can improve
performance.
With -j 4, the program returns in about 1/4 the time as with -j 1.
"""
import concurrent.futures
import multiprocessing
import time
import numpy as np
import rasterio
@ -18,7 +18,7 @@ from rasterio._example import compute
def main(infile, outfile, num_workers=4):
with rasterio.drivers():
with rasterio.Env():
# Open the source dataset.
with rasterio.open(infile) as src:
@ -87,4 +87,3 @@ if __name__ == '__main__':
args = parser.parse_args()
main(args.input, args.output, args.j)

View File

@ -4,7 +4,7 @@ import tempfile
import rasterio
with rasterio.drivers():
with rasterio.Env():
with rasterio.open('tests/data/RGB.byte.tif') as src:
b, g, r = (src.read(k) for k in (1, 2, 3))

View File

@ -6,7 +6,6 @@ import subprocess
import sys
import fiona
import numpy as np
import rasterio
from rasterio.features import shapes
@ -16,31 +15,31 @@ logger = logging.getLogger('rasterio_polygonize')
def main(raster_file, vector_file, driver, mask_value):
with rasterio.drivers():
with rasterio.Env():
with rasterio.open(raster_file) as src:
image = src.read(1)
if mask_value is not None:
mask = image == mask_value
else:
mask = None
results = (
{'properties': {'raster_val': v}, 'geometry': s}
for i, (s, v)
for i, (s, v)
in enumerate(
shapes(image, mask=mask, transform=src.affine)))
with fiona.open(
vector_file, 'w',
vector_file, 'w',
driver=driver,
crs=src.crs,
schema={'properties': [('raster_val', 'int')],
'geometry': 'Polygon'}) as dst:
dst.writerecords(results)
return dst.name
if __name__ == '__main__':
@ -48,11 +47,11 @@ if __name__ == '__main__':
parser = argparse.ArgumentParser(
description="Writes shapes of raster features to a vector file")
parser.add_argument(
'input',
metavar='INPUT',
'input',
metavar='INPUT',
help="Input file name")
parser.add_argument(
'output',
'output',
metavar='OUTPUT',
help="Output file name")
parser.add_argument(
@ -68,7 +67,6 @@ if __name__ == '__main__':
args = parser.parse_args()
name = main(args.input, args.output, args.output_driver, args.mask_value)
print subprocess.check_output(
['ogrinfo', '-so', args.output, name])

View File

@ -17,7 +17,7 @@ geometry = {
'coordinates': [[(2, 2), (2, 4.25), (4.25, 4.25), (4.25, 2), (2, 2)]]}
with rasterio.drivers():
with rasterio.Env():
result = rasterize([geometry], out_shape=(rows, cols))
with rasterio.open(
"test.tif",

View File

@ -1,7 +1,5 @@
import os
import shutil
import subprocess
import tempfile
import numpy as np
import rasterio
@ -11,12 +9,12 @@ from rasterio.warp import reproject, RESAMPLING
tempdir = '/tmp'
tiffname = os.path.join(tempdir, 'example.tif')
with rasterio.drivers():
with rasterio.Env():
# Consider a 512 x 512 raster centered on 0 degrees E and 0 degrees N
# with each pixel covering 15".
rows, cols = src_shape = (512, 512)
dpp = 1.0/240 # decimal degrees per pixel
dpp = 1.0/240 # decimal degrees per pixel
west, south, east, north = -cols*dpp/2, -rows*dpp/2, cols*dpp/2, rows*dpp/2
src_transform = transform.from_bounds(west, south, east, north, cols, rows)
src_crs = {'init': 'EPSG:4326'}
@ -30,8 +28,8 @@ with rasterio.drivers():
destination = np.zeros(dst_shape, np.uint8)
reproject(
source,
destination,
source,
destination,
src_transform=src_transform,
src_crs=src_crs,
dst_transform=dst_transform,
@ -44,7 +42,7 @@ with rasterio.drivers():
# Write it out to a file.
with rasterio.open(
tiffname,
tiffname,
'w',
driver='GTiff',
width=dst_shape[1],

View File

@ -10,15 +10,15 @@ from rasterio.features import sieve, shapes
# Register GDAL and OGR drivers.
with rasterio.drivers():
with rasterio.Env():
# Read a raster to be sieved.
with rasterio.open('tests/data/shade.tif') as src:
shade = src.read(1)
# Print the number of shapes in the source raster.
print("Slope shapes: %d" % len(list(shapes(shade))))
# Sieve out features 13 pixels or smaller.
sieved = sieve(shade, 13, out=np.zeros(src.shape, src.dtypes[0]))
@ -35,4 +35,3 @@ with rasterio.drivers():
print(subprocess.check_output(
['gdalinfo', '-stats', 'example-sieved.tif']))
subprocess.call(['open', 'example-sieved.tif'])

View File

@ -2,7 +2,7 @@ import numpy as np
import rasterio
import subprocess
with rasterio.drivers(CPL_DEBUG=True):
with rasterio.Env(CPL_DEBUG=True):
# Read raster bands directly to Numpy arrays.
with rasterio.open('tests/data/RGB.byte.tif') as src:
@ -35,4 +35,3 @@ info = subprocess.check_output(
['gdalinfo', '-stats', 'example-total.tif'])
print(info)
subprocess.call(['open', 'example-total.tif'])

View File

@ -18,7 +18,7 @@ from rasterio.dtypes import (
bool_, ubyte, uint8, uint16, int16, uint32, int32, float32, float64,
complex_, check_dtype)
from rasterio.env import ensure_env, Env
from rasterio.five import string_types
from rasterio.compat import string_types
from rasterio.profiles import default_gtiff_profile
from rasterio.transform import Affine, guard_transform
from rasterio.vfs import parse_path

View File

@ -5,7 +5,7 @@ import os
import os.path
import sys
from rasterio.five import string_types
from rasterio.compat import string_types
cdef extern from "cpl_conv.h":

View File

@ -23,7 +23,7 @@ from rasterio import dtypes
from rasterio.coords import BoundingBox
from rasterio.errors import (
DriverRegistrationError, RasterioIOError, NodataShadowWarning)
from rasterio.five import text_type, string_types
from rasterio.compat import text_type, string_types
from rasterio.transform import Affine
from rasterio.enums import ColorInterp, MaskFlags, Resampling
from rasterio.sample import sample_gen

View File

@ -24,22 +24,22 @@ cdef extern from "gdalwarper.h" nogil:
GDALWarpOperation() except +
int Initialize(const GDALWarpOptions *psNewOptions)
const GDALWarpOptions *GetOptions()
int ChunkAndWarpImage(
int ChunkAndWarpImage(
int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize )
int ChunkAndWarpMulti(
int ChunkAndWarpMulti(
int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize )
int WarpRegion( int nDstXOff, int nDstYOff,
int WarpRegion( int nDstXOff, int nDstYOff,
int nDstXSize, int nDstYSize,
int nSrcXOff=0, int nSrcYOff=0,
int nSrcXSize=0, int nSrcYSize=0,
double dfProgressBase=0.0, double dfProgressScale=1.0)
int WarpRegionToBuffer( int nDstXOff, int nDstYOff,
int nDstXSize, int nDstYSize,
void *pDataBuf,
int WarpRegionToBuffer( int nDstXOff, int nDstYOff,
int nDstXSize, int nDstYSize,
void *pDataBuf,
int eBufDataType,
int nSrcXOff=0, int nSrcYOff=0,
int nSrcXSize=0, int nSrcYSize=0,
double dfProgressBase=0.0,
double dfProgressBase=0.0,
double dfProgressScale=1.0)
@ -93,7 +93,7 @@ def _transform_geom(
_gdal.OSRDestroySpatialReference(src)
_gdal.OSRDestroySpatialReference(dst)
raise
# Transform options.
val_b = str(antimeridian_offset).encode('utf-8')
val_c = val_b
@ -269,13 +269,13 @@ def _reproject(
except:
raise DriverRegistrationError(
"'MEM' driver not found. Check that this call is contained "
"in a `with rasterio.drivers()` or `with rasterio.open()` "
"in a `with rasterio.Env()` or `with rasterio.open()` "
"block.")
try:
with CPLErrors() as cple:
hdsin = _gdal.GDALCreate(
hrdriver, "input", cols, rows,
hrdriver, "input", cols, rows,
src_count, dtypes.dtype_rev[dtype], NULL)
cple.check()
except:
@ -297,12 +297,12 @@ def _reproject(
finally:
_gdal.CPLFree(srcwkt)
_gdal.OSRDestroySpatialReference(osr)
# Copy arrays to the dataset.
retval = _io.io_auto(source, hdsin, 1)
# TODO: handle errors (by retval).
log.debug("Wrote array to temp source dataset")
# If the source is a rasterio Band, no copy necessary.
elif isinstance(source, tuple):
rdr = source.ds
@ -312,7 +312,7 @@ def _reproject(
src_nodata = rdr.nodata
else:
raise ValueError("Invalid source")
# Next, do the same for the destination raster.
if dtypes.is_ndarray(destination):
if len(destination.shape) == 2:
@ -327,14 +327,14 @@ def _reproject(
except:
raise DriverRegistrationError(
"'MEM' driver not found. Check that this call is contained "
"in a `with rasterio.drivers()` or `with rasterio.open()` "
"in a `with rasterio.Env()` or `with rasterio.open()` "
"block.")
_, rows, cols = destination.shape
try:
with CPLErrors() as cple:
hdsout = _gdal.GDALCreate(
hrdriver, "output", cols, rows, src_count,
hrdriver, "output", cols, rows, src_count,
dtypes.dtype_rev[np.dtype(destination.dtype).name], NULL)
cple.check()
except:
@ -372,7 +372,7 @@ def _reproject(
dst_nodata = udr.nodata
else:
raise ValueError("Invalid destination")
cdef void *hTransformArg = NULL
cdef _gdal.GDALWarpOptions *psWOptions = NULL
@ -398,7 +398,7 @@ def _reproject(
val_b = str(num_threads).encode('utf-8')
warp_extras = _gdal.CSLSetNameValue(warp_extras, "NUM_THREADS", val_b)
log.debug("Setting NUM_THREADS option: %s", val_b)
for k, v in kwargs.items():
k, v = k.upper(), str(v).upper()
key_b = k.encode('utf-8')
@ -540,7 +540,7 @@ def _calculate_default_transform(
extent[:] = [0.0, 0.0, 0.0, 0.0]
geotransform[:] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
# Make an in-memory raster dataset we can pass to
# Make an in-memory raster dataset we can pass to
# GDALCreateGenImgProjTransformer().
transform = from_bounds(left, bottom, right, top, width, height)
img = np.empty((height, width))

View File

@ -14,7 +14,7 @@ import json
from rasterio._base import is_geographic_crs, is_projected_crs, is_same_crs
from rasterio.errors import CRSError
from rasterio.five import string_types
from rasterio.compat import string_types
def is_valid_crs(crs):

View File

@ -6,7 +6,7 @@ from rasterio._drivers import (
GDALEnv, del_gdal_config, get_gdal_config, set_gdal_config)
from rasterio.dtypes import check_dtype
from rasterio.errors import EnvError
from rasterio.five import string_types
from rasterio.compat import string_types
from rasterio.transform import guard_transform
from rasterio.vfs import parse_path, vsi_path
@ -33,7 +33,7 @@ class Env(object):
Example:
with Env(GDAL_CACHEMAX=512) as env:
with rasterio.Env(GDAL_CACHEMAX=512) as env:
# All drivers are registered, GDAL's raster block cache
# size is set to 512MB.
# Commence processing...
@ -56,7 +56,7 @@ class Env(object):
"""Create a new GDAL/AWS environment.
Note: this class is a context manager. GDAL isn't configured
until the context is entered via `with Env():`
until the context is entered via `with rasterio.Env():`
Parameters
----------

View File

@ -28,7 +28,7 @@ except RuntimeError as e: # pragma: no cover
plt = None
from rasterio.five import zip_longest
from rasterio.compat import zip_longest
logger = logging.getLogger(__name__)

View File

@ -10,7 +10,6 @@ from cligj import (
from .helpers import write_features, to_lower
import rasterio
from rasterio.env import Env
from rasterio.warp import transform_bounds
logger = logging.getLogger('rio')
@ -107,7 +106,7 @@ def bounds(ctx, input, precision, indent, compact, projection, dst_crs,
self._ys.extend(bbox[1::2])
try:
with Env(CPL_DEBUG=verbosity > 2) as env:
with rasterio.Env(CPL_DEBUG=verbosity > 2) as env:
write_features(
stdout, Collection(env), sequence=sequence,
geojson_type=geojson_type, use_rs=use_rs,

View File

@ -10,7 +10,6 @@ from cligj import files_inout_arg
from .helpers import resolve_inout
from . import options
import rasterio
from rasterio.env import Env
from rasterio.fill import fillnodata
from rasterio.features import sieve
@ -90,7 +89,7 @@ def calc(ctx, command, files, output, name, dtype, masked, force_overwrite,
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
try:
with Env(CPL_DEBUG=verbosity > 2) as env:
with rasterio.Env(CPL_DEBUG=verbosity > 2):
output, files = resolve_inout(files=files, output=output,
force_overwrite=force_overwrite)

View File

@ -7,7 +7,6 @@ from .helpers import resolve_inout
from . import options
import rasterio
from rasterio.coords import disjoint_bounds
from rasterio.env import Env
# Clip command
@ -56,7 +55,7 @@ def clip(
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
with Env(CPL_DEBUG=verbosity > 2) as env:
with rasterio.Env(CPL_DEBUG=verbosity > 2):
output, files = resolve_inout(files=files, output=output)
input = files[0]

View File

@ -9,7 +9,6 @@ import numpy as np
from .helpers import resolve_inout
from . import options
import rasterio
from rasterio.env import Env
@click.command(short_help="Copy and convert raster dataset.")
@ -57,7 +56,7 @@ def convert(
"""
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
with Env(CPL_DEBUG=verbosity > 2) as env:
with rasterio.Env(CPL_DEBUG=verbosity > 2):
outputfile, files = resolve_inout(files=files, output=output)
inputfile = files[0]

View File

@ -8,7 +8,6 @@ import click
from . import options
import rasterio
import rasterio.crs
from rasterio.env import Env
from rasterio.transform import guard_transform
@ -126,7 +125,7 @@ def edit(ctx, input, nodata, crs, transform, tags, allmd, like):
rng = infos[np.dtype(dtype).kind](dtype)
return rng.min <= value <= rng.max
with Env(CPL_DEBUG=(verbosity > 2)) as env:
with rasterio.Env(CPL_DEBUG=(verbosity > 2)):
with rasterio.open(input, 'r+') as dst:

View File

@ -6,7 +6,6 @@ import click
import rasterio
import rasterio.crs
from rasterio.env import Env
@click.command(short_help="Print information about the rio environment.")
@ -19,7 +18,7 @@ def env(ctx, key):
"""
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
stdout = click.get_text_stream('stdout')
with Env(CPL_DEBUG=(verbosity > 2)) as env:
with rasterio.Env(CPL_DEBUG=(verbosity > 2)) as env:
if key == 'formats':
for k, v in sorted(env.drivers().items()):
stdout.write("%s: %s\n" % (k, v))

View File

@ -88,7 +88,7 @@ def resolve_inout(input=None, output=None, files=None, force_overwrite=False):
resolved_output):
raise FileOverwriteError(
"file exists and won't be overwritten without use of the "
"`-f` or `-o` options.")
"`--force-overwrite` or `--output` options.")
resolved_inputs = (
[input] if input else [] +
list(files[:-1 if not output else None]) if files else [])

View File

@ -6,7 +6,6 @@ import click
from . import options
import rasterio.crs
from rasterio.env import Env
@click.command(short_help="Print information about a data file.")
@ -63,7 +62,7 @@ def info(ctx, input, aspect, indent, namespace, meta_member, verbose, bidx,
verbosity = ctx.obj.get('verbosity')
mode = 'r' if (verbose or meta_member == 'stats') else 'r-'
try:
with Env(CPL_DEBUG=(verbosity > 2)):
with rasterio.Env(CPL_DEBUG=(verbosity > 2)):
with rasterio.open(input, mode) as src:
info = src.profile
info['transform'] = info['affine'][:6]

View File

@ -1,5 +1,4 @@
"""Fetch and edit raster dataset metadata from the command line.
"""
"""Fetch and edit raster dataset metadata from the command line."""
from __future__ import absolute_import
import code
@ -13,7 +12,6 @@ import click
from . import options
import rasterio
from rasterio.env import Env
from rasterio.plot import show, show_hist
try:
@ -39,8 +37,7 @@ funcs = locals()
def stats(source):
"""Return a tuple with raster min, max, and mean.
"""
"""Return a tuple with raster min, max, and mean."""
if isinstance(source, tuple):
arr = source[0].read(source[1])
else:
@ -49,7 +46,7 @@ def stats(source):
def main(banner, dataset, alt_interpreter=None):
""" Main entry point for use with python interpreter """
"""Main entry point for use with python interpreter."""
local = dict(funcs, src=dataset, np=np, rio=rasterio, plt=plt)
if not alt_interpreter:
code.interact(banner, local=local)
@ -75,12 +72,11 @@ def main(banner, dataset, alt_interpreter=None):
help="File mode (default 'r').")
@click.pass_context
def insp(ctx, input, mode, interpreter):
""" Open the input file in a Python interpreter.
"""
"""Open the input file in a Python interpreter."""
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
logger = logging.getLogger('rio')
try:
with Env(CPL_DEBUG=verbosity > 2) as env:
with rasterio.Env(CPL_DEBUG=verbosity > 2):
with rasterio.open(input, mode) as src:
main(
'Rasterio %s Interactive Inspector (Python %s)\n'

View File

@ -8,7 +8,6 @@ import cligj
from .helpers import resolve_inout
from . import options
import rasterio
from rasterio.env import Env
logger = logging.getLogger('rio')
@ -45,7 +44,6 @@ def mask(
invert,
force_overwrite,
creation_options):
"""Masks in raster using GeoJSON features (masks out all areas not covered
by features), and optionally crops the output raster to the extent of the
features. Features are assumed to be in the same coordinate reference
@ -67,7 +65,6 @@ def mask(
--crop option is not valid if features are completely outside extent of
input raster.
"""
from rasterio.mask import mask as mask_tool
from rasterio.features import bounds as calculate_bounds
@ -87,7 +84,7 @@ def mask(
click.echo('Invert option ignored when using --crop', err=True)
invert = False
with Env(CPL_DEBUG=verbosity > 2) as env:
with rasterio.Env(CPL_DEBUG=verbosity > 2):
try:
with click.open_file(geojson_mask) as fh:
geojson = json.loads(fh.read())

View File

@ -1,8 +1,6 @@
# Merge command.
"""Merge command."""
import logging
import math
import os.path
import click
from cligj import files_inout_arg, format_opt
@ -10,8 +8,6 @@ from cligj import files_inout_arg, format_opt
from .helpers import resolve_inout
from . import options
import rasterio
from rasterio.env import Env
from rasterio.transform import Affine
@click.command(short_help="Merge a stack of raster datasets.")
@ -48,7 +44,6 @@ def merge(ctx, files, output, driver, bounds, res, nodata, force_overwrite,
--res 0.1 0.1 => --res 0.1 (square)
--res 0.1 0.2 => --res 0.1 --res 0.2 (rectangular)
"""
from rasterio.merge import merge as merge_tool
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
@ -56,7 +51,7 @@ def merge(ctx, files, output, driver, bounds, res, nodata, force_overwrite,
output, files = resolve_inout(
files=files, output=output, force_overwrite=force_overwrite)
with Env(CPL_DEBUG=verbosity > 2) as env:
with rasterio.Env(CPL_DEBUG=verbosity > 2):
sources = [rasterio.open(f) for f in files]
dest, output_transform = merge_tool(sources, bounds=bounds, res=res,
nodata=nodata, precision=precision)

View File

@ -10,7 +10,6 @@ import click
from . import options
import rasterio
from rasterio.enums import Resampling
from rasterio.env import Env
def build_handler(ctx, param, value):
@ -69,7 +68,7 @@ def overview(ctx, input, build, ls, rebuild, resampling):
"""
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
with Env(CPL_DEBUG=(verbosity > 2)) as env:
with rasterio.Env(CPL_DEBUG=(verbosity > 2)):
with rasterio.open(input, 'r+') as dst:
if ls:

View File

@ -11,7 +11,6 @@ from . import options
import rasterio
from rasterio.transform import Affine
from rasterio.coords import disjoint_bounds
from rasterio.env import Env
logger = logging.getLogger('rio')
@ -68,7 +67,6 @@ def rasterize(
prop,
force_overwrite,
creation_options):
"""Rasterize GeoJSON into a new or existing raster.
If the output raster exists, rio-rasterize will rasterize feature values
@ -108,7 +106,6 @@ def rasterize(
of the output or --like rasters at this time. This functionality may be
added in the future.
"""
from rasterio._base import is_geographic_crs, is_same_crs
from rasterio.features import rasterize
from rasterio.features import bounds as calculate_bounds
@ -128,7 +125,7 @@ def rasterize(
if fill == int(fill):
fill = int(fill)
with Env(CPL_DEBUG=verbosity > 2):
with rasterio.Env(CPL_DEBUG=verbosity > 2):
def feature_value(feature):
if prop and 'properties' in feature:
@ -171,7 +168,7 @@ def rasterize(
all_touched=all_touched,
dtype=meta.get('dtype', None),
default_value=default_value,
fill = fill)
fill=fill)
for bidx in range(1, meta['count'] + 1):
data = out.read(bidx, masked=True)
@ -262,7 +259,7 @@ def rasterize(
all_touched=all_touched,
dtype=kwargs.get('dtype', None),
default_value=default_value,
fill = fill)
fill=fill)
if 'dtype' not in kwargs:
kwargs['dtype'] = result.dtype

View File

@ -4,7 +4,6 @@ import logging
import click
import rasterio
from rasterio.env import Env
@click.command(short_help="Sample a dataset.")
@ -67,7 +66,7 @@ def sample(ctx, files, bidx):
points = [input]
try:
with Env(CPL_DEBUG=verbosity > 2) as env:
with rasterio.Env(CPL_DEBUG=verbosity > 2):
with rasterio.open(source) as src:
if bidx is None:
indexes = src.indexes

View File

@ -7,7 +7,6 @@ import cligj
from .helpers import coords, write_features
from . import options
import rasterio
from rasterio.env import Env
from rasterio.transform import Affine
logger = logging.getLogger('rio')
@ -220,7 +219,7 @@ def shapes(
geojson_type = 'collection'
try:
with Env(CPL_DEBUG=(verbosity > 2)) as env:
with rasterio.Env(CPL_DEBUG=(verbosity > 2)) as env:
write_features(
stdout, Collection(env), sequence=sequence,
geojson_type=geojson_type, use_rs=use_rs,

View File

@ -8,8 +8,7 @@ from cligj import files_inout_arg, format_opt
from .helpers import resolve_inout
from . import options
import rasterio
from rasterio.env import Env
from rasterio.five import zip_longest
from rasterio.compat import zip_longest
# Stack command.
@ -55,11 +54,10 @@ def stack(ctx, files, output, driver, bidx, photometric, force_overwrite,
rio stack RGB.byte.tif --bidx ..2 RGB.byte.tif --bidx 3.. -o stacked.tif
"""
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 2
logger = logging.getLogger('rio')
try:
with Env(CPL_DEBUG=verbosity > 2) as env:
with rasterio.Env(CPL_DEBUG=verbosity > 2):
output, files = resolve_inout(files=files, output=output,
force_overwrite=force_overwrite)
output_count = 0

View File

@ -8,7 +8,6 @@ import click
from cligj import precision_opt
import rasterio
from rasterio.env import Env
@click.command(short_help="Transform coordinates.")
@ -32,7 +31,7 @@ def transform(ctx, input, src_crs, dst_crs, precision):
src = [input]
try:
with Env(CPL_DEBUG=verbosity > 2) as env:
with rasterio.Env(CPL_DEBUG=verbosity > 2):
if src_crs.startswith('EPSG'):
src_crs = {'init': src_crs}
elif os.path.exists(src_crs):

View File

@ -9,7 +9,6 @@ from .helpers import resolve_inout
from . import options
import rasterio
from rasterio import crs
from rasterio.env import Env
from rasterio.errors import CRSError
from rasterio.transform import Affine
from rasterio.warp import (
@ -48,7 +47,11 @@ def x_dst_bounds_handler(ctx, param, value):
@files_inout_arg
@options.output_opt
@format_opt
@options.like_file_opt
@click.option(
'--like',
type=click.Path(exists=True),
help='Raster dataset to use as a template for obtaining affine '
'transform (bounds and resolution), and crs.')
@click.option('--dst-crs', default=None,
help='Target coordinate reference system.')
@options.dimensions_opt
@ -72,6 +75,10 @@ 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('--src-nodata', default=None, show_default=True,
type=float, help="Manually override source nodata")
@click.option('--dst-nodata', default=None, show_default=True,
type=float, help="Manually override destination nodata")
@click.option('--threads', type=int, default=1,
help='Number of processing threads.')
@click.option('--check-invert-proj', type=bool, default=True,
@ -80,7 +87,7 @@ def x_dst_bounds_handler(ctx, param, value):
@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, check_invert_proj,
x_dst_bounds, bounds, res, resampling, src_nodata, dst_nodata, threads, check_invert_proj,
force_overwrite, creation_options):
"""
Warp a raster dataset.
@ -122,7 +129,6 @@ def warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds,
> --bounds -78 22 -76 24 --res 0.1 --dst-crs EPSG:4326
"""
verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
output, files = resolve_inout(
@ -137,8 +143,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 Env(CPL_DEBUG=verbosity > 2,
CHECK_WITH_INVERT_PROJ=check_invert_proj) as env:
with rasterio.Env(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()
@ -248,6 +254,26 @@ def warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds,
dst_width = src.width
dst_height = src.height
# If src_nodata is not None, update the dst metadata NODATA
# value to src_nodata (will be overridden by dst_nodata if it is not None
if src_nodata is not None:
# Update the dst nodata value
out_kwargs.update({
'nodata': src_nodata
})
# Validate a manually set destination NODATA value
# against the input datatype.
if dst_nodata is not None:
if src_nodata is None and src.meta['nodata'] is None:
raise click.BadParameter(
"--src-nodata must be provided because dst-nodata is not None")
else:
# Update the dst nodata value
out_kwargs.update({
'nodata': dst_nodata
})
# When the bounds option is misused, extreme values of
# destination width and height may result.
if (dst_width < 0 or dst_height < 0 or
@ -275,9 +301,9 @@ def warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds,
destination=rasterio.band(dst, i),
src_transform=src.affine,
src_crs=src.crs,
# src_nodata=#TODO
src_nodata=src_nodata,
dst_transform=out_kwargs['transform'],
dst_crs=out_kwargs['crs'],
# dst_nodata=#TODO
dst_nodata=dst_nodata,
resampling=resampling,
num_threads=threads)

View File

@ -2,7 +2,7 @@
import os
from rasterio.five import urlparse
from rasterio.compat import urlparse
# NB: As not to propagate fallacies of distributed computing, Rasterio

View File

@ -9,6 +9,7 @@
# source or binary distribution. This is essential when creating self-contained
# binary wheels.
import itertools
import logging
import os
import pprint
@ -220,6 +221,17 @@ inst_reqs = ['affine', 'cligj', 'numpy', 'snuggs', 'click-plugins']
if sys.version_info < (3, 4):
inst_reqs.append('enum34')
extra_reqs = {
'ipython': ['ipython>=2.0'],
's3': ['boto3>=1.2.4'],
'plot': ['matplotlib'],
'test': [
'pytest>=2.8.2', 'pytest-cov>=2.2.0', 'boto3>=1.2.4', 'packaging'],
'docs': ['ghp-import', 'numpydoc', 'sphinx', 'sphinx-rtd-theme']}
# Add all extra requirements
extra_reqs['all'] = list(set(itertools.chain(*extra_reqs.values())))
setup_args = dict(
name='rasterio',
version=version,
@ -276,12 +288,7 @@ setup_args = dict(
ext_modules=ext_modules,
zip_safe=False,
install_requires=inst_reqs,
extras_require={
'ipython': ['ipython>=2.0'],
's3': ['boto3>=1.2.4'],
'test': [
'pytest>=2.8.2', 'pytest-cov>=2.2.0', 'boto3>=1.2.4', 'packaging'],
'docs': ['ghp-import', 'numpydoc', 'sphinx', 'sphinx-rtd-theme']})
extras_require=extra_reqs)
if os.environ.get('PACKAGE_DATA'):
setup_args['package_data'] = {'rasterio': ['gdal_data/*', 'proj_data/*']}

View File

@ -1,22 +1,20 @@
import logging
import sys
import rasterio
from rasterio._drivers import driver_count
from rasterio.env import Env
def test_drivers():
with Env() as m:
with rasterio.Env() as m:
assert driver_count() > 0
assert type(m) == Env
assert type(m) == rasterio.Env
assert driver_count() > 0
def test_drivers_bwd_compat():
with rasterio.drivers() as m:
with rasterio.Env() as m:
assert driver_count() > 0
assert type(m) == Env
assert type(m) == rasterio.Env
assert driver_count() > 0
@ -28,7 +26,7 @@ def test_cpl_debug_true(tmpdir):
fh = logging.FileHandler(logfile)
log.addHandler(fh)
with Env(CPL_DEBUG=True):
with rasterio.Env(CPL_DEBUG=True):
with rasterio.open("tests/data/RGB.byte.tif"):
pass
@ -44,7 +42,7 @@ def test_cpl_debug_false(tmpdir):
fh = logging.FileHandler(logfile)
log.addHandler(fh)
with Env(CPL_DEBUG=False):
with rasterio.Env(CPL_DEBUG=False):
with rasterio.open("tests/data/RGB.byte.tif"):
pass

View File

@ -9,9 +9,9 @@ from packaging.version import parse
import pytest
import rasterio
from rasterio._drivers import (
GDALEnv, del_gdal_config, get_gdal_config, set_gdal_config, driver_count)
from rasterio.env import defenv, delenv, getenv, setenv, ensure_env, Env
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.errors import EnvError
from rasterio.rio.main import main_group
@ -45,7 +45,7 @@ def test_gdal_config_accessers():
# at the end of the test, making tests as isolates as GDAL allows.
def test_env_accessors(gdalenv):
"""High level GDAL env access"""
"""High level GDAL env access."""
defenv()
setenv(foo='1', bar='2')
assert getenv() == rasterio.env._env.options == {'foo': '1', 'bar': '2'}
@ -74,14 +74,14 @@ def test_ensure_env_decorator(gdalenv):
def test_no_aws_gdal_config(gdalenv):
"""Trying to set AWS-specific GDAL config options fails."""
with pytest.raises(EnvError):
Env(AWS_ACCESS_KEY_ID='x')
rasterio.Env(AWS_ACCESS_KEY_ID='x')
with pytest.raises(EnvError):
Env(AWS_SECRET_ACCESS_KEY='y')
rasterio.Env(AWS_SECRET_ACCESS_KEY='y')
def test_env_options(gdalenv):
"""Test env options."""
env = Env(foo='x')
env = rasterio.Env(foo='x')
assert env.options == {'foo': 'x'}
assert not env.previous_options
assert getenv() == rasterio.env._env.options == {}
@ -117,7 +117,7 @@ def test_aws_session_credentials(gdalenv):
def test_with_aws_session_credentials(gdalenv):
"""Create an Env with a boto3 session."""
with Env(aws_access_key_id='id', aws_secret_access_key='key',
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 == {}
s.get_aws_credentials()
@ -131,7 +131,7 @@ def test_session_env_lazy(monkeypatch, gdalenv):
monkeypatch.setenv('AWS_ACCESS_KEY_ID', 'id')
monkeypatch.setenv('AWS_SECRET_ACCESS_KEY', 'key')
monkeypatch.setenv('AWS_SESSION_TOKEN', 'token')
with Env() as s:
with rasterio.Env() as s:
s.get_aws_credentials()
assert getenv() == rasterio.env._env.options
expected = {
@ -152,7 +152,7 @@ def test_open_with_default_env(gdalenv):
def test_open_with_env(gdalenv):
"""Read from a dataset with an explicit env."""
with Env():
with rasterio.Env():
with rasterio.open('tests/data/RGB.byte.tif') as dataset:
assert dataset.count == 3
@ -161,7 +161,7 @@ def test_open_with_env(gdalenv):
@credentials
def test_s3_open_with_session(gdalenv):
"""Read from S3 demonstrating lazy credentials."""
with Env():
with rasterio.Env():
with rasterio.open(L8TIF) as dataset:
assert dataset.count == 1
@ -176,8 +176,8 @@ def test_s3_open_with_default_session(gdalenv):
@mingdalversion
def test_open_https_vsicurl(gdalenv):
"""Read from HTTPS URL"""
with Env():
"""Read from HTTPS URL."""
with rasterio.Env():
with rasterio.open(httpstif) as dataset:
assert dataset.count == 1
@ -187,7 +187,7 @@ def test_open_https_vsicurl(gdalenv):
@mingdalversion
@credentials
def test_s3_rio_info(runner):
"""S3 is supported by rio-info"""
"""S3 is supported by rio-info."""
result = runner.invoke(main_group, ['info', L8TIF])
assert result.exit_code == 0
assert '"crs": "EPSG:32645"' in result.output
@ -196,7 +196,7 @@ def test_s3_rio_info(runner):
@mingdalversion
@credentials
def test_https_rio_info(runner):
"""HTTPS is supported by rio-info"""
"""HTTPS is supported by rio-info."""
result = runner.invoke(main_group, ['info', httpstif])
assert result.exit_code == 0
assert '"crs": "EPSG:32645"' in result.output

View File

@ -5,7 +5,6 @@ import pytest
from affine import Affine
import rasterio
from rasterio.env import Env
from rasterio.features import bounds, geometry_mask, rasterize, sieve, shapes
@ -45,12 +44,11 @@ def test_feature_collection(basic_featurecollection):
def test_bounds_existing_bbox(basic_featurecollection):
"""
Test with existing bbox in geojson, similar to that produced by
rasterio. Values specifically modified here for testing, bboxes are not
valid as written.
"""
"""Test with existing bbox in geojson.
Similar to that produced by rasterio. Values specifically modified here
for testing, bboxes are not valid as written.
"""
fc = basic_featurecollection
fc['bbox'] = [0, 10, 10, 20]
fc['features'][0]['bbox'] = [0, 100, 10, 200]
@ -60,7 +58,7 @@ def test_bounds_existing_bbox(basic_featurecollection):
def test_geometry_mask(basic_geometry, basic_image_2x2):
with Env():
with rasterio.Env():
assert np.array_equal(
basic_image_2x2 == 0,
geometry_mask(
@ -72,7 +70,7 @@ def test_geometry_mask(basic_geometry, basic_image_2x2):
def test_geometry_mask_invert(basic_geometry, basic_image_2x2):
with Env():
with rasterio.Env():
assert np.array_equal(
basic_image_2x2,
geometry_mask(
@ -85,9 +83,8 @@ def test_geometry_mask_invert(basic_geometry, basic_image_2x2):
def test_rasterize(basic_geometry, basic_image_2x2):
""" Rasterize operation should succeed for both an out_shape and out """
with Env():
"""Rasterize operation should succeed for both an out_shape and out."""
with rasterio.Env():
assert np.array_equal(
basic_image_2x2,
rasterize([basic_geometry], out_shape=DEFAULT_SHAPE)
@ -99,35 +96,31 @@ def test_rasterize(basic_geometry, basic_image_2x2):
def test_rasterize_invalid_out_dtype(basic_geometry):
""" A non-supported data type for out should raise an exception """
"""A non-supported data type for out should raise an exception."""
out = np.zeros(DEFAULT_SHAPE, dtype=np.int64)
with Env():
with rasterio.Env():
with pytest.raises(ValueError):
rasterize([basic_geometry], out=out)
def test_rasterize_shapes_out_dtype_mismatch(basic_geometry):
""" Shape values must be able to fit in data type for out """
"""Shape values must be able to fit in data type for out."""
out = np.zeros(DEFAULT_SHAPE, dtype=np.uint8)
with Env():
with rasterio.Env():
with pytest.raises(ValueError):
rasterize([(basic_geometry, 10000000)], out=out)
def test_rasterize_missing_out(basic_geometry):
""" If both out and out_shape are missing, should raise exception """
with Env():
"""If both out and out_shape are missing, should raise exception."""
with rasterio.Env():
with pytest.raises(ValueError):
rasterize([basic_geometry], out=None, out_shape=None)
def test_rasterize_missing_shapes():
""" Shapes are required for this operation """
with Env():
"""Shapes are required for this operation."""
with rasterio.Env():
with pytest.raises(ValueError) as ex:
rasterize([], out_shape=DEFAULT_SHAPE)
@ -135,9 +128,8 @@ def test_rasterize_missing_shapes():
def test_rasterize_invalid_shapes():
""" Invalid shapes should raise an exception rather than be skipped """
with Env():
"""Invalid shapes should raise an exception rather than be skipped."""
with rasterio.Env():
with pytest.raises(ValueError) as ex:
rasterize([{'foo': 'bar'}], out_shape=DEFAULT_SHAPE)
@ -145,12 +137,11 @@ def test_rasterize_invalid_shapes():
def test_rasterize_default_value(basic_geometry, basic_image_2x2):
""" All shapes should rasterize to the default value """
"""All shapes should rasterize to the default value."""
default_value = 2
truth = basic_image_2x2 * default_value
with Env():
with rasterio.Env():
assert np.array_equal(
truth,
rasterize(
@ -161,9 +152,8 @@ def test_rasterize_default_value(basic_geometry, basic_image_2x2):
def test_rasterize_invalid_default_value(basic_geometry):
""" A default value that requires an int64 should raise an exception """
with Env():
"""A default value that requires an int64 should raise an exception."""
with rasterio.Env():
with pytest.raises(ValueError):
rasterize(
[basic_geometry], out_shape=DEFAULT_SHAPE,
@ -172,10 +162,9 @@ def test_rasterize_invalid_default_value(basic_geometry):
def test_rasterize_fill_value(basic_geometry, basic_image_2x2):
""" All pixels not covered by shapes should be given fill value """
"""All pixels not covered by shapes should be given fill value."""
default_value = 2
with Env():
with rasterio.Env():
assert np.array_equal(
basic_image_2x2 + 1,
rasterize(
@ -186,9 +175,8 @@ def test_rasterize_fill_value(basic_geometry, basic_image_2x2):
def test_rasterize_invalid_fill_value(basic_geometry):
""" A fill value that requires an int64 should raise an exception """
with Env():
"""A fill value that requires an int64 should raise an exception."""
with rasterio.Env():
with pytest.raises(ValueError):
rasterize(
[basic_geometry], out_shape=DEFAULT_SHAPE, fill=1000000000000,
@ -197,9 +185,8 @@ def test_rasterize_invalid_fill_value(basic_geometry):
def test_rasterize_fill_value_dtype_mismatch(basic_geometry):
""" A fill value that doesn't match dtype should fail """
with Env():
"""A fill value that doesn't match dtype should fail."""
with rasterio.Env():
with pytest.raises(ValueError):
rasterize(
[basic_geometry], out_shape=DEFAULT_SHAPE, fill=1000000,
@ -208,7 +195,7 @@ def test_rasterize_fill_value_dtype_mismatch(basic_geometry):
def test_rasterize_all_touched(basic_geometry, basic_image):
with Env():
with rasterio.Env():
assert np.array_equal(
basic_image,
rasterize(
@ -222,9 +209,8 @@ def test_rasterize_value(basic_geometry, basic_image_2x2):
All shapes should rasterize to the value passed in a tuple alongside
each shape
"""
value = 5
with Env():
with rasterio.Env():
assert np.array_equal(
basic_image_2x2 * value,
rasterize(
@ -234,9 +220,8 @@ def test_rasterize_value(basic_geometry, basic_image_2x2):
def test_rasterize_invalid_value(basic_geometry):
""" A shape value that requires an int64 should raise an exception """
with Env():
"""A shape value that requires an int64 should raise an exception."""
with rasterio.Env():
with pytest.raises(ValueError) as ex:
rasterize(
[(basic_geometry, 1000000000000)], out_shape=DEFAULT_SHAPE
@ -246,9 +231,8 @@ def test_rasterize_invalid_value(basic_geometry):
def test_rasterize_supported_dtype(basic_geometry):
""" Supported data types should return valid results """
with Env():
"""Supported data types should return valid results."""
with rasterio.Env():
supported_types = (
('int16', -32768),
('int32', -2147483648),
@ -284,9 +268,8 @@ def test_rasterize_supported_dtype(basic_geometry):
def test_rasterize_unsupported_dtype(basic_geometry):
""" Unsupported types should all raise exceptions """
with Env():
"""Unsupported types should all raise exceptions."""
with rasterio.Env():
unsupported_types = (
('int8', -127),
('int64', 20439845334323),
@ -311,9 +294,8 @@ def test_rasterize_unsupported_dtype(basic_geometry):
def test_rasterize_mismatched_dtype(basic_geometry):
""" Mismatched values and dtypes should raise exceptions """
with Env():
"""Mismatched values and dtypes should raise exceptions."""
with rasterio.Env():
mismatched_types = (('uint8', 3.2423), ('uint8', -2147483648))
for dtype, default_value in mismatched_types:
with pytest.raises(ValueError):
@ -333,27 +315,24 @@ def test_rasterize_mismatched_dtype(basic_geometry):
def test_rasterize_geometries_symmetric():
""" Make sure that rasterize is symmetric with shapes """
"""Make sure that rasterize is symmetric with shapes."""
transform = (1.0, 0.0, 0.0, 0.0, -1.0, 0.0)
truth = np.zeros(DEFAULT_SHAPE, dtype=rasterio.ubyte)
truth[2:5, 2:5] = 1
with Env():
with rasterio.Env():
s = shapes(truth, transform=transform)
result = rasterize(s, out_shape=DEFAULT_SHAPE, transform=transform)
assert np.array_equal(result, truth)
def test_rasterize_internal_driver_manager(basic_geometry):
""" Rasterize should work without explicitly calling driver manager """
"""Rasterize should work without explicitly calling driver manager."""
assert rasterize([basic_geometry], out_shape=DEFAULT_SHAPE).sum() == 4
def test_shapes(basic_image):
""" Test creation of shapes from pixel values """
with Env():
"""Test creation of shapes from pixel values."""
with rasterio.Env():
results = list(shapes(basic_image))
assert len(results) == 2
@ -379,9 +358,8 @@ def test_shapes(basic_image):
def test_shapes_band(pixelated_image, pixelated_image_file):
""" Shapes from a band should match shapes from an array """
with Env():
"""Shapes from a band should match shapes from an array."""
with rasterio.Env():
truth = list(shapes(pixelated_image))
with rasterio.open(pixelated_image_file) as src:
@ -397,8 +375,7 @@ def test_shapes_connectivity_rook(diagonal_image):
Diagonals are not connected, so there will be 1 feature per pixel plus
background.
"""
with Env():
with rasterio.Env():
assert len(list(shapes(diagonal_image, connectivity=4))) == 12
@ -407,26 +384,23 @@ def test_shapes_connectivity_queen(diagonal_image):
Diagonals are connected, so there will be 1 feature for all pixels plus
background.
"""
with Env():
with rasterio.Env():
assert len(list(shapes(diagonal_image, connectivity=8))) == 2
def test_shapes_connectivity_invalid(diagonal_image):
""" Invalid connectivity should raise exception """
with Env():
"""Invalid connectivity should raise exception."""
with rasterio.Env():
with pytest.raises(ValueError):
assert next(shapes(diagonal_image, connectivity=12))
def test_shapes_mask(basic_image):
""" Only pixels not masked out should be converted to features """
"""Only pixels not masked out should be converted to features."""
mask = np.ones(basic_image.shape, dtype=rasterio.bool_)
mask[4:5, 4:5] = False
with Env():
with rasterio.Env():
results = list(shapes(basic_image, mask=mask))
assert len(results) == 2
@ -442,9 +416,8 @@ def test_shapes_mask(basic_image):
def test_shapes_blank_mask(basic_image):
""" Mask is blank so results should mask shapes without mask """
with Env():
"""Mask is blank so results should mask shapes without mask."""
with rasterio.Env():
assert np.array_equal(
list(shapes(
basic_image,
@ -455,9 +428,8 @@ def test_shapes_blank_mask(basic_image):
def test_shapes_invalid_mask_shape(basic_image):
""" A mask that is the wrong shape should fail """
with Env():
"""A mask that is the wrong shape should fail."""
with rasterio.Env():
with pytest.raises(ValueError):
next(shapes(
basic_image,
@ -469,9 +441,8 @@ def test_shapes_invalid_mask_shape(basic_image):
def test_shapes_invalid_mask_dtype(basic_image):
""" A mask that is the wrong dtype should fail """
with Env():
"""A mask that is the wrong dtype should fail."""
with rasterio.Env():
for dtype in ('int8', 'int16', 'int32'):
with pytest.raises(ValueError):
next(shapes(
@ -481,8 +452,7 @@ def test_shapes_invalid_mask_dtype(basic_image):
def test_shapes_supported_dtypes(basic_image):
""" Supported data types should return valid results """
"""Supported data types should return valid results."""
supported_types = (
('int16', -32768),
('int32', -2147483648),
@ -491,15 +461,14 @@ def test_shapes_supported_dtypes(basic_image):
('float32', 1.434532)
)
with Env():
with rasterio.Env():
for dtype, test_value in supported_types:
shape, value = next(shapes(basic_image.astype(dtype) * test_value))
assert np.allclose(value, test_value)
def test_shapes_unsupported_dtypes(basic_image):
""" Unsupported data types should raise exceptions """
"""Unsupported data types should raise exceptions."""
unsupported_types = (
('int8', -127),
('uint32', 4294967295),
@ -508,15 +477,14 @@ def test_shapes_unsupported_dtypes(basic_image):
('float64', -98332.133422114)
)
with Env():
with rasterio.Env():
for dtype, test_value in unsupported_types:
with pytest.raises(ValueError):
next(shapes(basic_image.astype(dtype) * test_value))
def test_shapes_internal_driver_manager(basic_image):
""" Shapes should work without explicitly calling driver manager """
"""Shapes should work without explicitly calling driver manager."""
assert next(shapes(basic_image))[0]['type'] == 'Polygon'
@ -525,8 +493,7 @@ def test_sieve_small(basic_image, pixelated_image):
Setting the size smaller than or equal to the size of the feature in the
image should not change the image.
"""
with Env():
with rasterio.Env():
assert np.array_equal(
basic_image,
sieve(pixelated_image, basic_image.sum())
@ -537,29 +504,26 @@ def test_sieve_large(basic_image):
"""
Setting the size larger than size of feature should leave us an empty image.
"""
with Env():
with rasterio.Env():
assert not np.any(sieve(basic_image, basic_image.sum() + 1))
def test_sieve_invalid_size(basic_image):
with Env():
with rasterio.Env():
for invalid_size in (0, 45.1234, basic_image.size + 1):
with pytest.raises(ValueError):
sieve(basic_image, invalid_size)
def test_sieve_connectivity_rook(diagonal_image):
""" Diagonals are not connected, so feature is removed """
"""Diagonals are not connected, so feature is removed."""
assert not np.any(
sieve(diagonal_image, diagonal_image.sum(), connectivity=4)
)
def test_sieve_connectivity_queen(diagonal_image):
""" Diagonals are connected, so feature is retained """
"""Diagonals are connected, so feature is retained."""
assert np.array_equal(
diagonal_image,
sieve(diagonal_image, diagonal_image.sum(), connectivity=8)
@ -572,9 +536,8 @@ def test_sieve_connectivity_invalid(basic_image):
def test_sieve_out(basic_image):
""" Output array passed in should match the returned array """
with Env():
"""Output array passed in should match the returned array."""
with rasterio.Env():
output = np.zeros_like(basic_image)
output[1:3, 1:3] = 5
sieved_image = sieve(basic_image, basic_image.sum(), out=output)
@ -583,9 +546,8 @@ def test_sieve_out(basic_image):
def test_sieve_invalid_out(basic_image):
""" Output with different dtype or shape should fail """
with Env():
"""Output with different dtype or shape should fail."""
with rasterio.Env():
with pytest.raises(ValueError):
sieve(
basic_image, basic_image.sum(),
@ -607,12 +569,11 @@ def test_sieve_mask(basic_image):
Only areas within the overlap of mask and input will be kept, so long
as mask is a bool or uint8 dtype.
"""
mask = np.ones(basic_image.shape, dtype=rasterio.bool_)
mask[4:5, 4:5] = False
truth = basic_image * np.invert(mask)
with Env():
with rasterio.Env():
sieved_image = sieve(basic_image, basic_image.sum(), mask=mask)
assert sieved_image.sum() > 0
@ -628,10 +589,9 @@ def test_sieve_mask(basic_image):
def test_sieve_blank_mask(basic_image):
""" A blank mask should have no effect """
"""A blank mask should have no effect."""
mask = np.ones(basic_image.shape, dtype=rasterio.bool_)
with Env():
with rasterio.Env():
assert np.array_equal(
basic_image,
sieve(basic_image, basic_image.sum(), mask=mask)
@ -639,9 +599,8 @@ def test_sieve_blank_mask(basic_image):
def test_sieve_invalid_mask_shape(basic_image):
""" A mask that is the wrong shape should fail """
with Env():
"""A mask that is the wrong shape should fail."""
with rasterio.Env():
with pytest.raises(ValueError):
sieve(
basic_image, basic_image.sum(),
@ -653,9 +612,8 @@ def test_sieve_invalid_mask_shape(basic_image):
def test_sieve_invalid_mask_dtype(basic_image):
""" A mask that is the wrong dtype should fail """
with Env():
"""A mask that is the wrong dtype should fail."""
with rasterio.Env():
for dtype in ('int8', 'int16', 'int32'):
with pytest.raises(ValueError):
sieve(
@ -665,8 +623,7 @@ def test_sieve_invalid_mask_dtype(basic_image):
def test_sieve_supported_dtypes(basic_image):
""" Supported data types should return valid results """
"""Supported data types should return valid results."""
supported_types = (
('int16', -32768),
('int32', -2147483648),
@ -674,7 +631,7 @@ def test_sieve_supported_dtypes(basic_image):
('uint16', 65535)
)
with Env():
with rasterio.Env():
for dtype, test_value in supported_types:
truth = (basic_image).astype(dtype) * test_value
sieved_image = sieve(truth, basic_image.sum())
@ -683,8 +640,7 @@ def test_sieve_supported_dtypes(basic_image):
def test_sieve_unsupported_dtypes(basic_image):
""" Unsupported data types should raise exceptions """
"""Unsupported data types should raise exceptions."""
unsupported_types = (
('int8', -127),
('uint32', 4294967295),
@ -694,7 +650,7 @@ def test_sieve_unsupported_dtypes(basic_image):
('float64', -98332.133422114)
)
with Env():
with rasterio.Env():
for dtype, test_value in unsupported_types:
with pytest.raises(ValueError):
sieve(
@ -704,9 +660,8 @@ def test_sieve_unsupported_dtypes(basic_image):
def test_sieve_band(pixelated_image, pixelated_image_file):
""" Sieving a band from a raster file should match sieve of array """
with Env():
"""Sieving a band from a raster file should match sieve of array."""
with rasterio.Env():
truth = sieve(pixelated_image, 9)
with rasterio.open(pixelated_image_file) as src:
@ -721,8 +676,7 @@ def test_sieve_band(pixelated_image, pixelated_image_file):
def test_sieve_internal_driver_manager(basic_image, pixelated_image):
""" Sieve should work without explicitly calling driver manager """
"""Sieve should work without explicitly calling driver manager."""
assert np.array_equal(
basic_image,
sieve(pixelated_image, basic_image.sum())

View File

@ -6,12 +6,11 @@ See https://github.com/mapbox/rasterio/issues/293 for bug report.
import rasterio
from rasterio.enums import MaskFlags
from rasterio.env import Env
def test_create_internal_mask(data):
"""Write an internal mask to the fixture's RGB.byte.tif."""
with Env(GDAL_TIFF_INTERNAL_MASK=True):
with rasterio.Env(GDAL_TIFF_INTERNAL_MASK=True):
with rasterio.open(str(data.join('RGB.byte.tif')), 'r+') as dst:
blue = dst.read(1, masked=False)
mask = 255 * (blue == 0).astype('uint8')

View File

@ -57,6 +57,60 @@ def test_dst_crs_error_epsg_2(runner, tmpdir):
assert 'for dst_crs: EPSG codes are positive integers' in result.output
def test_dst_nodata_float_no_src_nodata_err(runner, tmpdir):
"""Valid integer destination nodata dtype"""
srcname = 'tests/data/float.tif'
outputname = str(tmpdir.join('test.tif'))
result = runner.invoke(main_group, [
'warp', srcname, outputname, '--dst-nodata', '0.0'])
assert result.exit_code == 2
assert 'src-nodata must be provided because dst-nodata is not None' in result.output
def test_src_nodata_int_ok(runner, tmpdir):
"""Check if input nodata is overridden"""
srcname = 'tests/data/RGB.byte.tif'
outputname = str(tmpdir.join('test.tif'))
result = runner.invoke(main_group, [
'warp', srcname, outputname, '--src-nodata', '1'])
assert result.exit_code == 0
with rasterio.open(outputname) as src:
assert src.meta['nodata'] == 1
def test_dst_nodata_int_ok(runner, tmpdir):
"""Check if input nodata is overridden"""
srcname = 'tests/data/RGB.byte.tif'
outputname = str(tmpdir.join('test.tif'))
result = runner.invoke(main_group, [
'warp', srcname, outputname, '--dst-nodata', '255'])
assert result.exit_code == 0
with rasterio.open(outputname) as src:
assert src.meta['nodata'] == 255
def test_src_nodata_float_ok(runner, tmpdir):
"""Check if input nodata is overridden"""
srcname = 'tests/data/float.tif'
outputname = str(tmpdir.join('test.tif'))
result = runner.invoke(main_group, [
'warp', srcname, outputname, '--src-nodata', '1.5'])
assert result.exit_code == 0
with rasterio.open(outputname) as src:
assert src.meta['nodata'] == 1.5
def test_dst_nodata_float_override_src_ok(runner, tmpdir):
"""Check if srcnodata is overridden"""
srcname = 'tests/data/float.tif'
outputname = str(tmpdir.join('test.tif'))
result = runner.invoke(main_group, [
'warp', srcname, outputname, '--src-nodata', '1.5', '--dst-nodata', '2.5'])
assert result.exit_code == 0
with rasterio.open(outputname) as src:
assert src.meta['nodata'] == 2.5
def test_warp_no_reproject(runner, tmpdir):
""" When called without parameters, output should be same as source """
srcname = 'tests/data/shade.tif'
@ -320,7 +374,7 @@ def test_warp_reproject_like(runner, tmpdir):
"nodata": 0
}
with rasterio.drivers():
with rasterio.Env():
with rasterio.open(likename, 'w', **kwargs) as dst:
data = np.zeros((10, 10), dtype=rasterio.uint8)
dst.write(data, indexes=1)

View File

@ -7,7 +7,6 @@ import numpy as np
import rasterio
from rasterio.enums import Resampling
from rasterio.env import Env
from rasterio.warp import (
reproject, transform_geom, transform, transform_bounds,
calculate_default_transform)
@ -20,7 +19,8 @@ DST_TRANSFORM = Affine.from_gdal(-8789636.708, 300.0, 0.0, 2943560.235, 0.0, -30
class ReprojectParams(object):
""" Class to assist testing reprojection by encapsulating parameters """
"""Class to assist testing reprojection by encapsulating parameters."""
def __init__(self, left, bottom, right, top, width, height, src_crs,
dst_crs):
self.width = width
@ -30,7 +30,7 @@ class ReprojectParams(object):
self.src_crs = src_crs
self.dst_crs = dst_crs
with Env():
with rasterio.Env():
dt, dw, dh = calculate_default_transform(
src_crs, dst_crs, width, height, left, bottom, right, top)
self.dst_transform = dt
@ -51,7 +51,7 @@ def default_reproject_params():
def test_transform():
"""2D and 3D"""
"""2D and 3D."""
WGS84_crs = {'init': 'EPSG:4326'}
WGS84_points = ([12.492269], [41.890169], [48.])
ECEF_crs = {'init': 'EPSG:4978'}
@ -66,7 +66,7 @@ def test_transform():
def test_transform_bounds():
with Env():
with rasterio.Env():
with rasterio.open('tests/data/RGB.byte.tif') as src:
l, b, r, t = src.bounds
assert np.allclose(
@ -111,8 +111,8 @@ def test_transform_bounds_densify():
def test_transform_bounds_no_change():
""" Make sure that going from and to the same crs causes no change """
with Env():
"""Make sure that going from and to the same crs causes no change."""
with rasterio.Env():
with rasterio.open('tests/data/RGB.byte.tif') as src:
l, b, r, t = src.bounds
assert np.allclose(
@ -136,7 +136,7 @@ def test_calculate_default_transform():
0.0028535715391804096, 0.0, -78.95864996545055,
0.0, -0.0028535715391804096, 25.550873767433984)
with Env():
with rasterio.Env():
with rasterio.open('tests/data/RGB.byte.tif') as src:
wgs84_crs = {'init': 'EPSG:4326'}
dst_transform, width, height = calculate_default_transform(
@ -148,7 +148,7 @@ def test_calculate_default_transform():
def test_calculate_default_transform_single_resolution():
with Env():
with rasterio.Env():
with rasterio.open('tests/data/RGB.byte.tif') as src:
target_resolution = 0.1
target_transform = Affine(
@ -166,7 +166,7 @@ def test_calculate_default_transform_single_resolution():
def test_calculate_default_transform_multiple_resolutions():
with Env():
with rasterio.Env():
with rasterio.open('tests/data/RGB.byte.tif') as src:
target_resolution = (0.2, 0.1)
target_transform = Affine(
@ -185,7 +185,7 @@ def test_calculate_default_transform_multiple_resolutions():
def test_reproject_ndarray():
with Env():
with rasterio.Env():
with rasterio.open('tests/data/RGB.byte.tif') as src:
source = src.read(1)
@ -215,7 +215,7 @@ def test_reproject_ndarray():
def test_reproject_epsg():
with Env():
with rasterio.Env():
with rasterio.open('tests/data/RGB.byte.tif') as src:
source = src.read(1)
@ -233,8 +233,11 @@ def test_reproject_epsg():
def test_reproject_out_of_bounds():
# using EPSG code not appropriate for the transform should return blank image
with Env():
"""Using EPSG code is not appropriate for the transform.
Should return blank image.
"""
with rasterio.Env():
with rasterio.open('tests/data/RGB.byte.tif') as src:
source = src.read(1)
@ -255,7 +258,7 @@ def test_reproject_nodata():
params = default_reproject_params()
nodata = 215
with Env():
with rasterio.Env():
source = np.ones((params.width, params.height), dtype=np.uint8)
out = np.zeros((params.dst_width, params.dst_height),
dtype=source.dtype)
@ -280,7 +283,7 @@ def test_reproject_nodata():
def test_reproject_nodata_nan():
params = default_reproject_params()
with Env():
with rasterio.Env():
source = np.ones((params.width, params.height), dtype=np.float32)
out = np.zeros((params.dst_width, params.dst_height),
dtype=source.dtype)
@ -299,18 +302,14 @@ def test_reproject_nodata_nan():
assert (out == 1).sum() == 6215
assert np.isnan(out).sum() == (params.dst_width *
params.dst_height - 6215)
params.dst_height - 6215)
def test_reproject_dst_nodata_default():
"""
If nodata is not provided, destination will be filled with 0
instead of nodata
"""
"""If nodata is not provided, destination will be filled with 0."""
params = default_reproject_params()
with Env():
with rasterio.Env():
source = np.ones((params.width, params.height), dtype=np.uint8)
out = np.zeros((params.dst_width, params.dst_height),
dtype=source.dtype)
@ -331,10 +330,10 @@ def test_reproject_dst_nodata_default():
def test_reproject_invalid_dst_nodata():
""" dst_nodata must be in value range of data type """
"""dst_nodata must be in value range of data type."""
params = default_reproject_params()
with Env():
with rasterio.Env():
source = np.ones((params.width, params.height), dtype=np.uint8)
out = source.copy()
@ -352,10 +351,10 @@ def test_reproject_invalid_dst_nodata():
def test_reproject_missing_src_nodata():
""" src_nodata is required if dst_nodata is not None """
"""src_nodata is required if dst_nodata is not None."""
params = default_reproject_params()
with Env():
with rasterio.Env():
source = np.ones((params.width, params.height), dtype=np.uint8)
out = source.copy()
@ -372,10 +371,10 @@ def test_reproject_missing_src_nodata():
def test_reproject_invalid_src_nodata():
""" src_nodata must be in range for data type """
"""src_nodata must be in range for data type."""
params = default_reproject_params()
with Env():
with rasterio.Env():
source = np.ones((params.width, params.height), dtype=np.uint8)
out = source.copy()
@ -393,8 +392,8 @@ def test_reproject_invalid_src_nodata():
def test_reproject_multi():
"""Ndarry to ndarray"""
with Env():
"""Ndarry to ndarray."""
with rasterio.Env():
with rasterio.open('tests/data/RGB.byte.tif') as src:
source = src.read()
dst_crs = dict(
@ -423,7 +422,7 @@ def test_reproject_multi():
def test_warp_from_file():
"""File to ndarray"""
"""File to ndarray."""
with rasterio.open('tests/data/RGB.byte.tif') as src:
dst_crs = dict(
proj='merc',
@ -448,7 +447,7 @@ def test_warp_from_file():
def test_warp_from_to_file(tmpdir):
"""File to file"""
"""File to file."""
tiffname = str(tmpdir.join('foo.tif'))
with rasterio.open('tests/data/RGB.byte.tif') as src:
dst_crs = dict(
@ -474,7 +473,7 @@ def test_warp_from_to_file(tmpdir):
def test_warp_from_to_file_multi(tmpdir):
"""File to file"""
"""File to file."""
tiffname = str(tmpdir.join('foo.tif'))
with rasterio.open('tests/data/RGB.byte.tif') as src:
dst_crs = dict(
@ -561,8 +560,8 @@ def test_transform_geom():
def test_reproject_unsupported_resampling():
"""Values not in enums.Resampling are not supported."""
with Env():
"""Values not in enums. Resampling are not supported."""
with rasterio.Env():
with rasterio.open('tests/data/RGB.byte.tif') as src:
source = src.read(1)
@ -581,7 +580,7 @@ def test_reproject_unsupported_resampling():
def test_reproject_unsupported_resampling_guass():
"""Resampling.gauss is unsupported."""
with Env():
with rasterio.Env():
with rasterio.open('tests/data/RGB.byte.tif') as src:
source = src.read(1)

View File

@ -4,9 +4,8 @@ import pytest
import rasterio
from rasterio._warp import _calculate_default_transform
from rasterio.env import Env
from rasterio.errors import CRSError
from rasterio.transform import Affine, from_bounds
from rasterio.transform import from_bounds
from rasterio.warp import transform_bounds
@ -21,7 +20,7 @@ def test_identity():
5009377.085697309)
transform = from_bounds(left, bottom, right, top, width, height)
with Env():
with rasterio.Env():
res_transform, res_width, res_height = _calculate_default_transform(
src_crs, dst_crs, width, height, left, bottom, right, top)
@ -33,7 +32,7 @@ def test_identity():
def test_transform_bounds():
"""CRSError is raised."""
with Env():
with rasterio.Env():
left, bottom, right, top = (
-11740727.544603072, 4852834.0517692715, -11584184.510675032,
5009377.085697309)
@ -44,7 +43,7 @@ def test_transform_bounds():
def test_gdal_transform_notnull():
with Env():
with rasterio.Env():
dt, dw, dh = _calculate_default_transform(
src_crs={'init': 'EPSG:4326'},
dst_crs={'init': 'EPSG:32610'},
@ -58,7 +57,7 @@ def test_gdal_transform_notnull():
def test_gdal_transform_fail_dst_crs():
with Env():
with rasterio.Env():
dt, dw, dh = _calculate_default_transform(
{'init': 'EPSG:4326'},
'+proj=foobar',
@ -69,8 +68,9 @@ def test_gdal_transform_fail_dst_crs():
right=-80,
top=70)
def test_gdal_transform_fail_src_crs():
with Env():
with rasterio.Env():
dt, dw, dh = _calculate_default_transform(
'+proj=foobar',
{'init': 'EPSG:32610'},
@ -86,7 +86,7 @@ def test_gdal_transform_fail_src_crs():
os.environ.get('GDALVERSION', 'a.b.c').startswith('1.9'),
reason="GDAL 1.9 doesn't catch this error")
def test_gdal_transform_fail_src_crs():
with Env():
with rasterio.Env():
with pytest.raises(CRSError):
dt, dw, dh = _calculate_default_transform(
{'init': 'EPSG:4326'},