[Git][debian-gis-team/rasterio][upstream] New upstream version 1.0.12
Bas Couwenberg
gitlab at salsa.debian.org
Tue Dec 11 08:47:26 GMT 2018
Bas Couwenberg pushed to branch upstream at Debian GIS Project / rasterio
Commits:
6f188a73 by Bas Couwenberg at 2018-12-11T08:29:24Z
New upstream version 1.0.12
- - - - -
17 changed files:
- CHANGES.txt
- rasterio/__init__.py
- rasterio/_features.pyx
- rasterio/_io.pxd
- rasterio/_io.pyx
- rasterio/_shim.pxd
- rasterio/_shim1.pyx
- rasterio/_shim20.pyx
- rasterio/rio/warp.py
- rasterio/shim_rasterioex.pxi
- rasterio/shutil.pyx
- rasterio/vrt.py
- rasterio/warp.py
- tests/test_overviews.py
- tests/test_shutil.py
- tests/test_vrt.py
- tests/test_warp.py
Changes:
=====================================
CHANGES.txt
=====================================
@@ -1,6 +1,23 @@
Changes
=======
+1.0.12 (2018-12-10)
+-------------------
+
+- Rasterio's lower level I/O functions now take Py_ssize_t index arrays and
+ will raise exceptions for type mismatches instead of swallowing the
+ exceptions (#1076).
+- The _boundless_vrt_doc function's background layer no longer needs an
+ in-memory dataset and the performance regression noted in #1499 has been
+ reversed. We've also found a performance improvement in masked boundless
+ reads in the case that the source data is entirely valid.
+- The signature of the private _boundless_vrt_doc function in rasterio.vrt has
+ changed. Its background keyword argument now takes an int or float, a new
+ masked keyword argument has been added, and the function returns a unicode
+ str instead of ascii-encoded bytes.
+- The copy and copyfiles functions of rasterio.shutil now raise an exception
+ when the source and destination paths identify the same dataset (#1569).
+
1.0.11 (2019-11-30)
-------------------
=====================================
rasterio/__init__.py
=====================================
@@ -42,7 +42,7 @@ import rasterio.path
__all__ = ['band', 'open', 'pad', 'Env']
-__version__ = "1.0.11"
+__version__ = "1.0.12"
__gdal_version__ = gdal_version()
# Rasterio attaches NullHandler to the 'rasterio' logger and its
=====================================
rasterio/_features.pyx
=====================================
@@ -309,8 +309,8 @@ def _rasterize(shapes, image, transform, all_touched, merge_alg):
with InMemoryRaster(image=image, transform=transform) as mem:
exc_wrap_int(
GDALRasterizeGeometries(
- mem.handle(), 1, mem.band_ids,num_geoms, geoms, NULL,
- mem.gdal_transform, pixel_values, options, NULL, NULL))
+ mem.handle(), 1, mem.band_ids, num_geoms, geoms, NULL,
+ NULL, pixel_values, options, NULL, NULL))
# Read in-memory data back into image
image = mem.read()
=====================================
rasterio/_io.pxd
=====================================
@@ -50,4 +50,4 @@ ctypedef np.float64_t DTYPE_FLOAT64_t
cdef bint in_dtype_range(value, dtype)
-cdef int io_auto(image, GDALRasterBandH band, bint write, int resampling=*)
+cdef int io_auto(image, GDALRasterBandH band, bint write, int resampling=*) except -1
=====================================
rasterio/_io.pyx
=====================================
@@ -104,7 +104,7 @@ cdef bint in_dtype_range(value, dtype):
return rng.min <= value <= rng.max
-cdef int io_auto(data, GDALRasterBandH band, bint write, int resampling=0):
+cdef int io_auto(data, GDALRasterBandH band, bint write, int resampling=0) except -1:
"""Convenience function to handle IO with a GDAL band.
:param data: a numpy ndarray
@@ -121,7 +121,7 @@ cdef int io_auto(data, GDALRasterBandH band, bint write, int resampling=0):
return io_band(band, write, 0.0, 0.0, width, height, data,
resampling=resampling)
elif ndims == 3:
- indexes = np.arange(1, data.shape[0] + 1)
+ indexes = np.arange(1, data.shape[0] + 1).astype('int')
return io_multi_band(band, write, 0.0, 0.0, width, height, data,
indexes, resampling=resampling)
else:
@@ -367,23 +367,15 @@ cdef class DatasetReaderBase(DatasetBase):
else:
if fill_value is not None:
- dtype = self.dtypes[0]
- bg_path = UnparsedPath('/vsimem/bg{}.tif'.format(uuid.uuid4()))
- with DatasetWriterBase(
- bg_path, 'w',
- driver='GTiff', count=self.count, height=3, width=3,
- dtype=dtype, crs=None, transform=Affine.identity() * Affine.translation(1, 1)) as bg_dataset:
- bg_dataset.write(
- np.full((self.count, 3, 3), fill_value, dtype=dtype))
- bg_dataset = DatasetReaderBase(bg_path)
+ nodataval = fill_value
else:
- bg_dataset = None
+ nodataval = ndv
vrt_doc = _boundless_vrt_doc(
- self, nodata=ndv, background=bg_dataset,
+ self, nodata=nodataval, background=nodataval,
width=max(self.width, window.width) + 1,
height=max(self.height, window.height) + 1,
- transform=self.window_transform(window)).decode('ascii')
+ transform=self.window_transform(window))
if not gdal_version().startswith('1'):
vrt_kwds = {'driver': 'VRT'}
@@ -396,58 +388,43 @@ cdef class DatasetReaderBase(DatasetBase):
indexes, out, Window(0, 0, window.width, window.height),
None, resampling=resampling)
- if masked and all_valid:
- blank_path = UnparsedPath('/vsimem/blank-{}.tif'.format(uuid.uuid4()))
- transform = Affine.translation(self.transform.xoff, self.transform.yoff) * (Affine.scale(self.width / 3, self.height / 3) * (Affine.translation(-self.transform.xoff, -self.transform.yoff) * self.transform))
- with DatasetWriterBase(
- blank_path, 'w',
- driver='GTiff', count=self.count, height=3, width=3,
- dtype='uint8', crs=self.crs, transform=transform) as blank_dataset:
- blank_dataset.write(
- np.ones((self.count, 3, 3), dtype='uint8'))
-
- with DatasetReaderBase(blank_path) as blank_dataset:
+ if masked:
+
+ # Below we use another VRT to compute the valid data mask
+ # in this special case where all source pixels are valid.
+ if all_valid:
+
mask_vrt_doc = _boundless_vrt_doc(
- blank_dataset, nodata=0,
+ self, nodata=0,
width=max(self.width, window.width) + 1,
height=max(self.height, window.height) + 1,
- transform=self.window_transform(window)).decode('ascii')
+ transform=self.window_transform(window),
+ masked=True)
with DatasetReaderBase(UnparsedPath(mask_vrt_doc), **vrt_kwds) as mask_vrt:
mask = np.zeros(out.shape, 'uint8')
mask = ~mask_vrt._read(
indexes, mask, Window(0, 0, window.width, window.height), None).astype('bool')
- kwds = {'mask': mask}
- # Set a fill value only if the read bands share a
- # single nodata value.
- if fill_value is not None:
- kwds['fill_value'] = fill_value
- elif len(set(nodatavals)) == 1:
- if nodatavals[0] is not None:
- kwds['fill_value'] = nodatavals[0]
-
- out = np.ma.array(out, **kwds)
- elif masked:
- mask = np.zeros(out.shape, 'uint8')
- mask = ~vrt._read(
- indexes, mask, Window(0, 0, window.width, window.height), None, masks=True).astype('bool')
+ else:
+ mask = np.zeros(out.shape, 'uint8')
+ mask = ~vrt._read(
+ indexes, mask, Window(0, 0, window.width, window.height), None, masks=True).astype('bool')
kwds = {'mask': mask}
+
# Set a fill value only if the read bands share a
# single nodata value.
if fill_value is not None:
kwds['fill_value'] = fill_value
+
elif len(set(nodatavals)) == 1:
if nodatavals[0] is not None:
kwds['fill_value'] = nodatavals[0]
out = np.ma.array(out, **kwds)
- if bg_dataset is not None:
- bg_dataset.close()
-
if return2d:
out.shape = out.shape[1:]
@@ -601,7 +578,7 @@ cdef class DatasetReaderBase(DatasetBase):
blank_dataset, nodata=0,
width=max(self.width, window.width) + 1,
height=max(self.height, window.height) + 1,
- transform=self.window_transform(window)).decode('ascii')
+ transform=self.window_transform(window))
with DatasetReaderBase(UnparsedPath(mask_vrt_doc), **vrt_kwds) as mask_vrt:
out = np.zeros(out.shape, 'uint8')
@@ -612,7 +589,7 @@ cdef class DatasetReaderBase(DatasetBase):
vrt_doc = _boundless_vrt_doc(
self, width=max(self.width, window.width) + 1,
height=max(self.height, window.height) + 1,
- transform=self.window_transform(window)).decode('ascii')
+ transform=self.window_transform(window))
with DatasetReaderBase(UnparsedPath(vrt_doc), **vrt_kwds) as vrt:
@@ -693,7 +670,7 @@ cdef class DatasetReaderBase(DatasetBase):
# Call io_multi* functions with C type args so that they
# can release the GIL.
- indexes_arr = np.array(indexes, dtype=int)
+ indexes_arr = np.array(indexes).astype('int')
indexes_count = <int>indexes_arr.shape[0]
if masks:
=====================================
rasterio/_shim.pxd
=====================================
@@ -1,14 +1,7 @@
include "gdal.pxi"
-cdef GDALDatasetH open_dataset(object filename, int mode,
- object allowed_drivers, object open_options,
- object siblings) except NULL
+cdef GDALDatasetH open_dataset(object filename, int mode, object allowed_drivers, object open_options, object siblings) except NULL
cdef int delete_nodata_value(GDALRasterBandH hBand) except 3
-cdef int io_band(GDALRasterBandH band, int mode, float xoff, float yoff,
- float width, float height, object data, int resampling=*)
-cdef int io_multi_band(GDALDatasetH hds, int mode, float xoff, float yoff,
- float width, float height, object data, long[:] indexes,
- int resampling=*)
-cdef int io_multi_mask(GDALDatasetH hds, int mode, float xoff, float yoff,
- float width, float height, object data, long[:] indexes,
- int resampling=*)
+cdef int io_band(GDALRasterBandH band, int mode, float xoff, float yoff, float width, float height, object data, int resampling=*) except -1
+cdef int io_multi_band(GDALDatasetH hds, int mode, float xoff, float yoff, float width, float height, object data, Py_ssize_t[:] indexes, int resampling=*) except -1
+cdef int io_multi_mask(GDALDatasetH hds, int mode, float xoff, float yoff, float width, float height, object data, Py_ssize_t[:] indexes, int resampling=*) except -1
=====================================
rasterio/_shim1.pyx
=====================================
@@ -55,8 +55,9 @@ cdef int delete_nodata_value(GDALRasterBandH hBand) except 3:
"GDAL versions < 2.1 do not support nodata deletion")
-cdef int io_band(GDALRasterBandH band, int mode, float x0, float y0,
- float width, float height, object data, int resampling=0):
+cdef int io_band(
+ GDALRasterBandH band, int mode, float x0, float y0,
+ float width, float height, object data, int resampling=0) except -1:
"""Read or write a region of data for the band.
Implicit are
@@ -90,9 +91,9 @@ cdef int io_band(GDALRasterBandH band, int mode, float x0, float y0,
return retval
-cdef int io_multi_band(GDALDatasetH hds, int mode, float x0, float y0,
- float width, float height, object data,
- long[:] indexes, int resampling=0):
+cdef int io_multi_band(
+ GDALDatasetH hds, int mode, float x0, float y0, float width,
+ float height, object data, Py_ssize_t[:] indexes, int resampling=0) except -1:
"""Read or write a region of data for multiple bands.
Implicit are
@@ -123,7 +124,7 @@ cdef int io_multi_band(GDALDatasetH hds, int mode, float x0, float y0,
with nogil:
bandmap = <int *>CPLMalloc(count*sizeof(int))
for i in range(count):
- bandmap[i] = indexes[i]
+ bandmap[i] = <int>indexes[i]
retval = GDALDatasetRasterIO(
hds, mode, xoff, yoff, xsize, ysize, buf,
bufxsize, bufysize, buftype, count, bandmap,
@@ -133,9 +134,9 @@ cdef int io_multi_band(GDALDatasetH hds, int mode, float x0, float y0,
return retval
-cdef int io_multi_mask(GDALDatasetH hds, int mode, float x0, float y0,
- float width, float height, object data,
- long[:] indexes, int resampling=0):
+cdef int io_multi_mask(
+ GDALDatasetH hds, int mode, float x0, float y0, float width,
+ float height, object data, Py_ssize_t[:] indexes, int resampling=0) except -1:
"""Read or write a region of data for multiple band masks.
Implicit are
@@ -165,7 +166,7 @@ cdef int io_multi_mask(GDALDatasetH hds, int mode, float x0, float y0,
cdef int ysize = <int>height
for i in range(count):
- j = indexes[i]
+ j = <int>indexes[i]
band = GDALGetRasterBand(hds, j)
if band == NULL:
raise ValueError("Null band")
=====================================
rasterio/_shim20.pyx
=====================================
@@ -12,7 +12,7 @@ include "shim_rasterioex.pxi"
# Declarations and implementations specific for GDAL = 2.0
cdef extern from "gdal.h" nogil:
- GDALDatasetH GDALOpenEx(const char *filename, int flags, const char **allowed_drivers, const char **options, const char **siblings) # except -1
+ GDALDatasetH GDALOpenEx(const char *filename, int flags, const char **allowed_drivers, const char **options, const char **siblings)
from rasterio._err cimport exc_wrap_pointer
=====================================
rasterio/rio/warp.py
=====================================
@@ -1,15 +1,13 @@
"""$ rio warp"""
-import logging
-from math import ceil, log
-import warnings
+from math import ceil
import click
from cligj import format_opt
import rasterio
from rasterio.crs import CRS
-from rasterio.env import setenv, GDALVersion
+from rasterio.env import setenv
from rasterio.errors import CRSError
from rasterio.rio import options
from rasterio.rio.helpers import resolve_inout
@@ -150,8 +148,8 @@ def warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds,
with rasterio.open(files[0]) as src:
l, b, r, t = src.bounds
- out_kwargs = src.profile.copy()
- out_kwargs['driver'] = driver
+ out_kwargs = src.profile
+ out_kwargs.update(driver=driver)
# Sort out the bounds options.
if src_bounds and dst_bounds:
@@ -271,9 +269,7 @@ def warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds,
# 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
- })
+ out_kwargs.update(nodata=src_nodata)
# Validate a manually set destination NODATA value
# against the input datatype.
@@ -283,7 +279,7 @@ def warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds,
"--src-nodata must be provided because dst-nodata is not None")
else:
# Update the dst nodata value
- out_kwargs.update({'nodata': dst_nodata})
+ out_kwargs.update(nodata=dst_nodata)
# When the bounds option is misused, extreme values of
# destination width and height may result.
@@ -294,12 +290,12 @@ def warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds,
"Invalid output dimensions: {0}.".format(
(dst_width, dst_height)))
- out_kwargs.update({
- 'crs': dst_crs,
- 'transform': dst_transform,
- 'width': dst_width,
- 'height': dst_height
- })
+ out_kwargs.update(
+ crs=dst_crs,
+ transform=dst_transform,
+ width=dst_width,
+ height=dst_height
+ )
# Adjust block size if necessary.
if ('blockxsize' in out_kwargs and
=====================================
rasterio/shim_rasterioex.pxi
=====================================
@@ -31,7 +31,7 @@ cdef extern from "gdal.h" nogil:
cdef int io_band(GDALRasterBandH band, int mode, float x0, float y0,
- float width, float height, object data, int resampling=0):
+ float width, float height, object data, int resampling=0) except -1:
"""Read or write a region of data for the band.
Implicit are
@@ -78,7 +78,7 @@ cdef int io_band(GDALRasterBandH band, int mode, float x0, float y0,
cdef int io_multi_band(GDALDatasetH hds, int mode, float x0, float y0,
float width, float height, object data,
- long[:] indexes, int resampling=0):
+ Py_ssize_t[:] indexes, int resampling=0) except -1:
"""Read or write a region of data for multiple bands.
Implicit are
@@ -120,7 +120,7 @@ cdef int io_multi_band(GDALDatasetH hds, int mode, float x0, float y0,
with nogil:
bandmap = <int *>CPLMalloc(count*sizeof(int))
for i in range(count):
- bandmap[i] = indexes[i]
+ bandmap[i] = <int>indexes[i]
retval = GDALDatasetRasterIOEx(
hds, <GDALRWFlag>mode, xoff, yoff, xsize, ysize, buf,
bufxsize, bufysize, buftype, count, bandmap,
@@ -132,7 +132,7 @@ cdef int io_multi_band(GDALDatasetH hds, int mode, float x0, float y0,
cdef int io_multi_mask(GDALDatasetH hds, int mode, float x0, float y0,
float width, float height, object data,
- long[:] indexes, int resampling=0):
+ Py_ssize_t[:] indexes, int resampling=0) except -1:
"""Read or write a region of data for multiple band masks.
Implicit are
@@ -173,7 +173,7 @@ cdef int io_multi_mask(GDALDatasetH hds, int mode, float x0, float y0,
extras.pProgressData = NULL
for i in range(count):
- j = indexes[i]
+ j = <int>indexes[i]
band = GDALGetRasterBand(hds, j)
if band == NULL:
raise ValueError("Null band")
=====================================
rasterio/shutil.pyx
=====================================
@@ -1,10 +1,15 @@
-"""Raster management."""
-
+"""Raster file management."""
include "gdal.pxi"
import logging
+try:
+ from pathlib import Path
+except ImportError: # pragma: no cover
+ class Path:
+ pass
+
from rasterio._io cimport DatasetReaderBase
from rasterio._err cimport exc_wrap_int, exc_wrap_pointer
from rasterio.env import ensure_env_with_credentials
@@ -55,9 +60,9 @@ def copy(src, dst, driver='GTiff', strict=True, **creation_options):
Parameters
----------
- src : str or dataset object opened in 'r' mode
+ src : str or pathlib.Path or dataset object opened in 'r' mode
Source dataset
- dst : str
+ dst : str or pathlib.Path
Output dataset path
driver : str, optional
Output driver name
@@ -66,6 +71,11 @@ def copy(src, dst, driver='GTiff', strict=True, **creation_options):
driver may adapt as necessary
creation_options : **kwargs, optional
Creation options for output dataset
+
+ Returns
+ -------
+ None
+
"""
cdef bint c_strictness
@@ -87,29 +97,47 @@ def copy(src, dst, driver='GTiff', strict=True, **creation_options):
c_strictness = strict
driverb = driver.encode('utf-8')
drv = GDALGetDriverByName(driverb)
+
if drv == NULL:
raise DriverRegistrationError("Unrecognized driver: {}".format(driver))
- # Input is a path or GDAL connection string
+ # Convert src and dst Paths to strings.
+ if isinstance(src, Path):
+ src = str(src)
+ if isinstance(dst, Path):
+ dst = str(dst)
+
+ # Open a new GDAL dataset if src is a string.
if isinstance(src, str):
+
+ if vsi_path(parse_path(src)) == vsi_path(parse_path(dst)):
+ raise RasterioIOError("{} and {} identify the same dataset.".format(src, dst))
+
src = src.encode('utf-8')
c_src_path = src
with nogil:
src_dataset = GDALOpenShared(c_src_path, <GDALAccess>0)
src_dataset = exc_wrap_pointer(src_dataset)
close_src = True
- # Input is something like 'rasterio.open()'
+
+ # Try to use the existing GDAL dataset handle otherwise.
else:
+
+ if src.name == vsi_path(parse_path(dst)):
+ raise RasterioIOError("{} and {} identify the same dataset.".format(src.name, dst))
+
src_dataset = (<DatasetReaderBase?>src).handle()
close_src = False
dst = dst.encode('utf-8')
c_dst_path = dst
+
try:
with nogil:
dst_dataset = GDALCreateCopy(
drv, c_dst_path, src_dataset, c_strictness, options, NULL, NULL)
dst_dataset = exc_wrap_pointer(dst_dataset)
+
finally:
CSLDestroy(options)
with nogil:
@@ -127,19 +155,35 @@ def copyfiles(src, dst):
Parameters
----------
- src : str
+ src : str or pathlib.Path
Source dataset
- dst : str
+ dst : str or pathlib.Path
Target dataset
+
+ Returns
+ -------
+ None
+
"""
cdef GDALDatasetH h_dataset = NULL
cdef GDALDriverH h_driver = NULL
+ # Convert src and dst Paths to strings.
+ if isinstance(src, Path):
+ src = str(src)
+ if isinstance(dst, Path):
+ dst = str(dst)
+
+ src_path = parse_path(src)
+ dst_path = parse_path(dst)
+ if vsi_path(src_path) == vsi_path(dst_path):
+ raise RasterioIOError("{} and {} identify the same dataset.".format(src, dst))
+
# VFS paths probabaly don't work, but its hard to be completely certain
# so just attempt to use them.
- gdal_src_path = vsi_path(parse_path(src))
- gdal_dst_path = vsi_path(parse_path(dst))
+ gdal_src_path = vsi_path(src_path)
+ gdal_dst_path = vsi_path(dst_path)
b_gdal_src_path = gdal_src_path.encode('utf-8')
b_gdal_dst_path = gdal_dst_path.encode('utf-8')
cdef char* c_gdal_src_path = b_gdal_src_path
=====================================
rasterio/vrt.py
=====================================
@@ -71,21 +71,22 @@ class WarpedVRT(WarpedVRTReaderBase, WindowMethodsMixin,
def _boundless_vrt_doc(
src_dataset, nodata=None, background=None, hidenodata=False,
- width=None, height=None, transform=None):
+ width=None, height=None, transform=None, masked=False):
"""Make a VRT XML document.
Parameters
----------
src_dataset : Dataset
The dataset to wrap.
- background : Dataset, optional
- A dataset that provides the optional VRT background. NB: this dataset
- must have the same number of bands as the src_dataset.
+ background : int or float, optional
+ The background fill value for the boundless VRT.
+ masked : book
+ If True, the src_dataset is replaced by its valid data mask.
Returns
-------
- bytes
- An ascii-encoded string (an ElementTree detail)
+ str
+ An XML text string.
"""
nodata = nodata or src_dataset.nodata
@@ -118,56 +119,69 @@ def _boundless_vrt_doc(
colorinterp.text = ci.name.capitalize()
if background is not None:
- simplesource = ET.SubElement(vrtrasterband, 'SimpleSource')
- sourcefilename = ET.SubElement(simplesource, 'SourceFilename')
- sourcefilename.attrib['relativeToVRT'] = "0"
- sourcefilename.text = vsi_path(parse_path(background.name))
- sourceband = ET.SubElement(simplesource, 'SourceBand')
+ complexsource = ET.SubElement(vrtrasterband, 'ComplexSource')
+ sourcefilename = ET.SubElement(complexsource, 'SourceFilename')
+ sourcefilename.attrib['relativeToVRT'] = '1'
+ sourcefilename.text = 'dummy.tif' # vsi_path(parse_path(background.name))
+ sourceband = ET.SubElement(complexsource, 'SourceBand')
sourceband.text = str(bidx)
- sourceproperties = ET.SubElement(simplesource, 'SourceProperties')
+ sourceproperties = ET.SubElement(complexsource, 'SourceProperties')
sourceproperties.attrib['RasterXSize'] = str(width)
sourceproperties.attrib['RasterYSize'] = str(height)
sourceproperties.attrib['dataType'] = _gdal_typename(dtype)
sourceproperties.attrib['BlockYSize'] = str(block_shape[0])
sourceproperties.attrib['BlockXSize'] = str(block_shape[1])
- srcrect = ET.SubElement(simplesource, 'SrcRect')
+ srcrect = ET.SubElement(complexsource, 'SrcRect')
srcrect.attrib['xOff'] = '0'
srcrect.attrib['yOff'] = '0'
- srcrect.attrib['xSize'] = str(background.width)
- srcrect.attrib['ySize'] = str(background.height)
- dstrect = ET.SubElement(simplesource, 'DstRect')
+ srcrect.attrib['xSize'] = '1' # str(background.width)
+ srcrect.attrib['ySize'] = '1' # str(background.height)
+ dstrect = ET.SubElement(complexsource, 'DstRect')
dstrect.attrib['xOff'] = '0'
dstrect.attrib['yOff'] = '0'
- dstrect.attrib['xSize'] = str(width)
- dstrect.attrib['ySize'] = str(height)
-
- simplesource = ET.SubElement(vrtrasterband, 'SimpleSource')
- sourcefilename = ET.SubElement(simplesource, 'SourceFilename')
+ dstrect.attrib['xSize'] = '1' # str(width)
+ dstrect.attrib['ySize'] = '1' # str(height)
+ scaleratio = ET.SubElement(complexsource, 'ScaleRatio')
+ scaleratio.text = '0'
+ scaleoffset = ET.SubElement(complexsource, 'ScaleOffset')
+ scaleoffset.text = str(background)
+
+ complexsource = ET.SubElement(vrtrasterband, 'ComplexSource')
+ sourcefilename = ET.SubElement(complexsource, 'SourceFilename')
sourcefilename.attrib['relativeToVRT'] = "0"
sourcefilename.text = vsi_path(parse_path(src_dataset.name))
- sourceband = ET.SubElement(simplesource, 'SourceBand')
+ sourceband = ET.SubElement(complexsource, 'SourceBand')
sourceband.text = str(bidx)
- sourceproperties = ET.SubElement(simplesource, 'SourceProperties')
+ sourceproperties = ET.SubElement(complexsource, 'SourceProperties')
sourceproperties.attrib['RasterXSize'] = str(width)
sourceproperties.attrib['RasterYSize'] = str(height)
sourceproperties.attrib['dataType'] = _gdal_typename(dtype)
sourceproperties.attrib['BlockYSize'] = str(block_shape[0])
sourceproperties.attrib['BlockXSize'] = str(block_shape[1])
- srcrect = ET.SubElement(simplesource, 'SrcRect')
+ srcrect = ET.SubElement(complexsource, 'SrcRect')
srcrect.attrib['xOff'] = '0'
srcrect.attrib['yOff'] = '0'
srcrect.attrib['xSize'] = str(src_dataset.width)
srcrect.attrib['ySize'] = str(src_dataset.height)
- dstrect = ET.SubElement(simplesource, 'DstRect')
+ dstrect = ET.SubElement(complexsource, 'DstRect')
dstrect.attrib['xOff'] = str((src_dataset.transform.xoff - transform.xoff) / transform.a)
dstrect.attrib['yOff'] = str((src_dataset.transform.yoff - transform.yoff) / transform.e)
dstrect.attrib['xSize'] = str(src_dataset.width * src_dataset.transform.a / transform.a)
dstrect.attrib['ySize'] = str(src_dataset.height * src_dataset.transform.e / transform.e)
if src_dataset.nodata is not None:
- nodata_elem = ET.SubElement(simplesource, 'NODATA')
+ nodata_elem = ET.SubElement(complexsource, 'NODATA')
nodata_elem.text = str(src_dataset.nodata)
+ # Effectively replaces all values of the source dataset with
+ # 255. Due to GDAL optimizations, the source dataset will not
+ # be read, so we get a performance improvement.
+ if masked:
+ scaleratio = ET.SubElement(complexsource, 'ScaleRatio')
+ scaleratio.text = '0'
+ scaleoffset = ET.SubElement(complexsource, 'ScaleOffset')
+ scaleoffset.text = '255'
+
if all(MaskFlags.per_dataset in flags for flags in src_dataset.mask_flag_enums):
maskband = ET.SubElement(vrtdataset, 'MaskBand')
vrtrasterband = ET.SubElement(maskband, 'VRTRasterBand')
@@ -197,4 +211,4 @@ def _boundless_vrt_doc(
dstrect.attrib['xSize'] = str(src_dataset.width)
dstrect.attrib['ySize'] = str(src_dataset.height)
- return ET.tostring(vrtdataset)
+ return ET.tostring(vrtdataset).decode('ascii')
=====================================
rasterio/warp.py
=====================================
@@ -212,8 +212,8 @@ def reproject(source, destination, src_transform=None, gcps=None,
Will be derived from source if it is a rasterio Band.
Example: CRS({'init': 'EPSG:4326'})
src_nodata: int or float, optional
- The source nodata value.Pixels with this value will not be
- used for interpolation. If not set, it will be default to the
+ The source nodata value. Pixels with this value will not be
+ used for interpolation. If not set, it will default to the
nodata value of the source image if a masked ndarray or
rasterio band, if available.
dst_transform: affine.Affine(), optional
=====================================
tests/test_overviews.py
=====================================
@@ -2,6 +2,8 @@
import pytest
+from .conftest import requires_gdal2
+
import rasterio
from rasterio.enums import Resampling
from rasterio.env import GDALVersion
@@ -90,6 +92,7 @@ def test_issue1333(data):
overview_factors, resampling=Resampling.average)
+ at requires_gdal2
def test_build_overviews_new_file(tmpdir, path_rgb_byte_tif):
"""Confirm fix of #1497"""
dst_file = str(tmpdir.join('test.tif'))
=====================================
tests/test_shutil.py
=====================================
@@ -52,6 +52,14 @@ def test_exists(path_rgb_byte_tif):
assert not rasterio.shutil.exists('trash')
+def test_copy_fail_same_dataset(data):
+ """A dataset can't be copied to itself."""
+ path = str(data.join('RGB.byte.tif'))
+ with pytest.raises(RasterioIOError):
+ with rasterio.open(path) as src:
+ rasterio.shutil.copy(src, path, **src.profile)
+
+
@pytest.mark.parametrize("pass_handle", (True, False))
def test_copy(tmpdir, path_rgb_byte_tif, pass_handle):
@@ -143,6 +151,20 @@ def test_copyfiles(data, tmpdir):
assert all(map(os.path.exists, actual.files))
+def test_copyfiles_same_dataset(data):
+ """A dataset can't be copied to itself."""
+ path = str(data.join('RGB.byte.tif'))
+ with pytest.raises(RasterioIOError):
+ rasterio.shutil.copyfiles(path, path)
+
+
+def test_copyfiles_same_dataset_another_name(data):
+ """A dataset can't be copied to itself by another name."""
+ path = str(data.join('RGB.byte.tif'))
+ with pytest.raises(RasterioIOError):
+ rasterio.shutil.copyfiles(path, 'file://' + path)
+
+
def test_copyfiles_fail():
with pytest.raises(RasterioIOError):
rasterio.shutil.copyfiles('trash', 'whatever')
=====================================
tests/test_vrt.py
=====================================
@@ -7,8 +7,8 @@ import rasterio.vrt
def test_boundless_vrt(path_rgb_byte_tif):
with rasterio.open(path_rgb_byte_tif) as rgb:
doc = rasterio.vrt._boundless_vrt_doc(rgb)
- assert doc.startswith(b'<VRTDataset')
- with rasterio.open(doc.decode('ascii')) as vrt:
+ assert doc.startswith('<VRTDataset')
+ with rasterio.open(doc) as vrt:
assert rgb.count == vrt.count
assert rgb.dtypes == vrt.dtypes
assert rgb.mask_flag_enums == vrt.mask_flag_enums
@@ -17,8 +17,8 @@ def test_boundless_vrt(path_rgb_byte_tif):
def test_boundless_msk_vrt(path_rgb_msk_byte_tif):
with rasterio.open(path_rgb_msk_byte_tif) as msk:
doc = rasterio.vrt._boundless_vrt_doc(msk)
- assert doc.startswith(b'<VRTDataset')
- with rasterio.open(doc.decode('ascii')) as vrt:
+ assert doc.startswith('<VRTDataset')
+ with rasterio.open(doc) as vrt:
assert msk.count == vrt.count
assert msk.dtypes == vrt.dtypes
assert msk.mask_flag_enums == vrt.mask_flag_enums
=====================================
tests/test_warp.py
=====================================
@@ -1472,3 +1472,23 @@ def test_issue_1446_b():
}
# Before the fix, this geometry was thrown eastward of 0.0. It should be between -350 and -250.
assert all([-350 < x < -150 for x, y in transformed_geoms[183519]["coordinates"]])
+
+
+def test_issue_1076():
+ """Confirm fix of #1076"""
+ arr = (np.random.random((20, 30)) * 100).astype('int32')
+ fill_value = 42
+ newarr = np.full((200, 300), fill_value=fill_value, dtype='int32')
+
+ src_crs = {'init': 'EPSG:32632'}
+ src_transform = Affine(600.0, 0.0, 399960.0, 0.0, -600.0, 6100020.0)
+ dst_transform = Affine(60.0, 0.0, 399960.0, 0.0, -60.0, 6100020.0)
+
+ reproject(arr, newarr,
+ src_transform=src_transform,
+ dst_transform=dst_transform,
+ src_crs=src_crs,
+ dst_crs=src_crs,
+ resample=Resampling.nearest)
+
+ assert not (newarr == fill_value).all()
View it on GitLab: https://salsa.debian.org/debian-gis-team/rasterio/commit/6f188a73e893ba541abf58b34cfacb692d6b3278
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/rasterio/commit/6f188a73e893ba541abf58b34cfacb692d6b3278
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20181211/b19731b1/attachment-0001.html>
More information about the Pkg-grass-devel
mailing list