[Git][debian-gis-team/rasterio][master] 4 commits: New upstream version 1.0.2

Bas Couwenberg gitlab at salsa.debian.org
Sat Jul 28 09:11:03 BST 2018


Bas Couwenberg pushed to branch master at Debian GIS Project / rasterio


Commits:
3b435c7b by Bas Couwenberg at 2018-07-28T06:33:58Z
New upstream version 1.0.2
- - - - -
4cff5983 by Bas Couwenberg at 2018-07-28T06:34:04Z
Merge tag 'upstream/1.0.2'

Upstream version 1.0.2

- - - - -
c8508802 by Bas Couwenberg at 2018-07-28T06:35:25Z
New upstream release.

- - - - -
f4e4d1d6 by Bas Couwenberg at 2018-07-28T06:36:23Z
Set distribution to unstable.

- - - - -


12 changed files:

- CHANGES.txt
- debian/changelog
- rasterio/__init__.py
- rasterio/_base.pyx
- rasterio/_warp.pyx
- rasterio/rio/warp.py
- rasterio/warp.py
- + tests/data/rotated.tif
- tests/test_coords.py
- tests/test_rio_warp.py
- tests/test_warp.py
- tests/test_warp_transform.py


Changes:

=====================================
CHANGES.txt
=====================================
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,18 @@
 Changes
 =======
 
+1.0.2 (2018-07-27)
+------------------
+
+Bug fixes:
+
+- The output of calculate_default_transform() can be fixed to output dimensions
+  as well as to output resolution (#1409).
+- In using rio-warp, the --src-bounds option can now override the bounds of the
+  source dataset when --dimensions is used (#1419).
+- Bounds of rotated rasters are now calculated correctly (#1422).
+- A band indexing bug in reproject() (#1350) has been fixed (#1424).
+
 1.0.1 (2018-07-23)
 ------------------
 


=====================================
debian/changelog
=====================================
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+rasterio (1.0.2-1) unstable; urgency=medium
+
+  * Team upload.
+  * New upstream release.
+
+ -- Bas Couwenberg <sebastic at debian.org>  Sat, 28 Jul 2018 08:36:14 +0200
+
 rasterio (1.0.1-1) unstable; urgency=medium
 
   * Team upload.


=====================================
rasterio/__init__.py
=====================================
--- a/rasterio/__init__.py
+++ b/rasterio/__init__.py
@@ -43,7 +43,7 @@ import rasterio.path
 
 
 __all__ = ['band', 'open', 'pad', 'Env']
-__version__ = "1.0.1"
+__version__ = "1.0.2"
 __gdal_version__ = gdal_version()
 
 # Rasterio attaches NullHandler to the 'rasterio' logger and its


=====================================
rasterio/_base.pyx
=====================================
--- a/rasterio/_base.pyx
+++ b/rasterio/_base.pyx
@@ -788,7 +788,18 @@ cdef class DatasetBase(object):
         """
         def __get__(self):
             a, b, c, d, e, f, _, _, _ = self.transform
-            return BoundingBox(c, f + e * self.height, c + a * self.width, f)
+            width = self.width
+            height = self.height
+            if b == d == 0:
+                return BoundingBox(c, f + e * height, c + a * width, f)
+            else:
+                c0x, c0y = c, f
+                c1x, c1y = self.transform * (0, height)
+                c2x, c2y = self.transform * (width, height)
+                c3x, c3y = self.transform * (width, 0)
+                xs = (c0x, c1x, c2x, c3x)
+                ys = (c0y, c1y, c2y, c3y)
+                return BoundingBox(min(xs), min(ys), max(xs), max(ys))
 
     property res:
         """Returns the (width, height) of pixels in the units of its


=====================================
rasterio/_warp.pyx
=====================================
--- a/rasterio/_warp.pyx
+++ b/rasterio/_warp.pyx
@@ -433,8 +433,14 @@ def _reproject(
     if dtypes.is_ndarray(destination):
         if len(destination.shape) == 2:
             destination = destination.reshape(1, *destination.shape)
-            dst_bidx = [1]
+
+        if destination.shape[0] == src_count:
+            # Output shape matches number of bands being extracted
+            dst_bidx = [i + 1 for i in range(src_count)]
         else:
+            # Assume src and dst are the same shape
+            if max(src_bidx) > destination.shape[0]:
+                raise ValueError("Invalid destination shape")
             dst_bidx = src_bidx
 
         try:
@@ -565,6 +571,11 @@ def _reproject(
     psWOptions.hSrcDS = src_dataset
     psWOptions.hDstDS = dst_dataset
 
+    for idx, (s, d) in enumerate(zip(src_bidx, dst_bidx)):
+        psWOptions.panSrcBands[idx] = s
+        psWOptions.panDstBands[idx] = d
+        log.debug('Configured to warp src band %d to destination band %d' % (s, d))
+
     log.debug("Set transformer options")
 
     # Now that the transformer and warp options are set up, we init


=====================================
rasterio/rio/warp.py
=====================================
--- a/rasterio/rio/warp.py
+++ b/rasterio/rio/warp.py
@@ -231,6 +231,7 @@ def warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds,
                 # Same projection, different dimensions, calculate resolution.
                 dst_crs = src.crs
                 dst_width, dst_height = dimensions
+                l, b, r, t = src_bounds or (l, b, r, t)
                 dst_transform = Affine(
                     (r - l) / float(dst_width),
                     0, l, 0,


=====================================
rasterio/warp.py
=====================================
--- a/rasterio/warp.py
+++ b/rasterio/warp.py
@@ -342,7 +342,7 @@ def aligned_target(transform, width, height, resolution):
 @ensure_env
 def calculate_default_transform(
         src_crs, dst_crs, width, height, left=None, bottom=None, right=None,
-        top=None, gcps=None, resolution=None):
+        top=None, gcps=None, resolution=None, dst_width=None, dst_height=None):
     """Output dimensions and transform for a reprojection.
 
     Source and destination coordinate reference systems and output
@@ -374,6 +374,9 @@ def calculate_default_transform(
     resolution: tuple (x resolution, y resolution) or float, optional
         Target resolution, in units of target coordinate reference
         system.
+    dst_width, dst_height: int, optional
+        Output file size in pixels and lines. Cannot be used together
+        with resolution.
 
     Returns
     -------
@@ -398,6 +401,18 @@ def calculate_default_transform(
     if any(x is None for x in (left, bottom, right, top)) and not gcps:
         raise ValueError("Either four bounding values or ground control points"
                          "must be specified")
+    
+    if (dst_width is None) != (dst_height is None):
+        raise ValueError("Either dst_width and dst_height must be specified "
+                         "or none of them.")
+
+    if all(x is not None for x in (dst_width, dst_height)):
+        dimensions = (dst_width, dst_height)
+    else:
+        dimensions = None
+
+    if resolution and dimensions:
+        raise ValueError("Resolution cannot be used with dst_width and dst_height.")
 
     dst_affine, dst_width, dst_height = _calculate_default_transform(
         src_crs, dst_crs, width, height, left, bottom, right, top, gcps)
@@ -426,5 +441,15 @@ def calculate_default_transform(
 
         dst_width = ceil(dst_width * xratio)
         dst_height = ceil(dst_height * yratio)
+    
+    if dimensions:
+        xratio = dst_width / dimensions[0]
+        yratio = dst_height / dimensions[1]
+
+        dst_width = dimensions[0]
+        dst_height = dimensions[1]
+        
+        dst_affine = Affine(dst_affine.a * xratio, dst_affine.b, dst_affine.c,
+                            dst_affine.d, dst_affine.e * yratio, dst_affine.f)
 
     return dst_affine, dst_width, dst_height


=====================================
tests/data/rotated.tif
=====================================
Binary files /dev/null and b/tests/data/rotated.tif differ


=====================================
tests/test_coords.py
=====================================
--- a/tests/test_coords.py
+++ b/tests/test_coords.py
@@ -1,4 +1,5 @@
 import rasterio
+import numpy as np
 
 def test_bounds():
     with rasterio.open('tests/data/RGB.byte.tif') as src:
@@ -13,3 +14,10 @@ def test_ul():
 def test_res():
     with rasterio.open('tests/data/RGB.byte.tif') as src:
         assert tuple(round(v, 6) for v in src.res) == (300.037927, 300.041783)
+
+def test_rotated_bounds():
+    with rasterio.open('tests/data/rotated.tif') as src:
+        assert src.res == (20.0, 10.0)
+        np.testing.assert_almost_equal(
+            src.bounds,
+            (100.0, 70.0961894323342, 348.20508075688775, 300.0))


=====================================
tests/test_rio_warp.py
=====================================
--- a/tests/test_rio_warp.py
+++ b/tests/test_rio_warp.py
@@ -212,6 +212,28 @@ def test_warp_no_reproject_bounds_res(runner, tmpdir):
             assert np.allclose(output.bounds, out_bounds)
 
 
+def test_warp_no_reproject_src_bounds_dimensions(runner, tmpdir):
+    """--src-bounds option works with dimensions"""
+    srcname = 'tests/data/shade.tif'
+    outputname = str(tmpdir.join('test.tif'))
+    out_bounds = [-11850000, 4810000, -11849000, 4812000]
+    result = runner.invoke(
+        main_group, [
+            'warp', srcname, outputname, '--dimensions', 9, 14,
+            '--src-bounds'] + out_bounds)
+    assert result.exit_code == 0
+    assert os.path.exists(outputname)
+
+    with rasterio.open(srcname) as src:
+        with rasterio.open(outputname) as output:
+            assert output.crs == src.crs
+            assert np.allclose(output.bounds, out_bounds)
+            assert np.allclose([111.111111, 142.857142],
+                               [output.transform.a, -output.transform.e])
+            assert output.width == 9
+            assert output.height == 14
+
+
 def test_warp_reproject_dst_crs(runner, tmpdir):
     srcname = 'tests/data/RGB.byte.tif'
     outputname = str(tmpdir.join('test.tif'))


=====================================
tests/test_warp.py
=====================================
--- a/tests/test_warp.py
+++ b/tests/test_warp.py
@@ -253,6 +253,24 @@ def test_calculate_default_transform_multiple_resolutions():
         assert height == 20
 
 
+def test_calculate_default_transform_dimensions():
+    with rasterio.open('tests/data/RGB.byte.tif') as src:
+        dst_width, dst_height = (113, 103)
+        target_transform = Affine(
+            0.02108612597535966, 0.0, -78.95864996545055,
+            0.0, -0.0192823863230055, 25.550873767433984
+        )
+
+        dst_transform, width, height = calculate_default_transform(
+            src.crs, {'init': 'EPSG:4326'}, src.width, src.height,
+            *src.bounds, dst_width=dst_width, dst_height=dst_height
+        )
+
+        assert dst_transform.almost_equals(target_transform)
+        assert width == dst_width
+        assert height == dst_height
+
+
 def test_reproject_ndarray():
     with rasterio.open('tests/data/RGB.byte.tif') as src:
         source = src.read(1)
@@ -1268,3 +1286,31 @@ def test_reproject_dst_alpha(path_rgb_msk_byte_tif):
             dst_alpha=4)
 
         assert dst_arr[3].any()
+
+
+ at pytest.mark.xfail(
+    rasterio.__gdal_version__ in ['2.2.0', '2.2.1', '2.2.2', '2.2.3'],
+    reason=("GDAL had regression in 2.2.X series, fixed in 2.2.4,"
+            " reproject used dst index instead of src index when destination was single band"))
+def test_issue1350():
+    """Warp bands other than 1 or All"""
+
+    with rasterio.open('tests/data/RGB.byte.tif') as src:
+        dst_crs = {'init': 'EPSG:3857'}
+
+        reprojected = []
+
+        for dtype, idx in zip(src.dtypes, src.indexes):
+            out = np.zeros((1,) + src.shape, dtype=dtype)
+
+            reproject(
+                rasterio.band(src, idx),
+                out,
+                resampling=Resampling.nearest,
+                dst_transform=DST_TRANSFORM,
+                dst_crs=dst_crs)
+
+            reprojected.append(out)
+
+        for i in range(1, len(reprojected)):
+            assert not (reprojected[0] == reprojected[i]).all()


=====================================
tests/test_warp_transform.py
=====================================
--- a/tests/test_warp_transform.py
+++ b/tests/test_warp_transform.py
@@ -16,6 +16,27 @@ def test_gcps_bounds_exclusivity():
             'epsg:4326', 'epsg:3857', width=1, height=1, left=1.0, gcps=[1])
 
 
+def test_resolution_dimensions_exclusivity():
+    """resolution and dimensions parameters are mutually exclusive"""
+    with pytest.raises(ValueError):
+        calculate_default_transform(
+            'epsg:4326', 'epsg:3857', width=1, height=1, gcps=[1],
+            resolution=1, dst_width=1, dst_height=1)
+
+
+def test_dimensions_missing_params():
+    """dst_width and dst_height must be specified together"""
+    with pytest.raises(ValueError):
+        calculate_default_transform(
+            'epsg:4326', 'epsg:3857', width=1, height=1, gcps=[1],
+            resolution=1, dst_width=1, dst_height=None)
+
+    with pytest.raises(ValueError):
+        calculate_default_transform(
+            'epsg:4326', 'epsg:3857', width=1, height=1, gcps=[1],
+            resolution=1, dst_width=None, dst_height=1)
+
+
 def test_one_of_gcps_bounds():
     """at least one of gcps or bounds parameters must be provided"""
     with pytest.raises(ValueError):



View it on GitLab: https://salsa.debian.org/debian-gis-team/rasterio/compare/d2379ce40bbc10a06b38cecbfaa5cdd96f5f5225...f4e4d1d61f3651be9c53cad0da9dc5f3f158017c

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/rasterio/compare/d2379ce40bbc10a06b38cecbfaa5cdd96f5f5225...f4e4d1d61f3651be9c53cad0da9dc5f3f158017c
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/20180728/bc0a5456/attachment-0001.html>


More information about the Pkg-grass-devel mailing list