def test_read_with_reproject(tmpdir):
    from datacube.testutils import mk_test_image
    from datacube.testutils.io import write_gtiff
    from pathlib import Path

    pp = Path(str(tmpdir))

    xx = mk_test_image(128, 64, nodata=None)
    assert (xx != -999).all()
    tile = AlbersGS.tile_geobox((17, -40))[:64, :128]

    mm = write_gtiff(pp / 'tst-read-with-reproject-128x64-int16.tif',
                     xx,
                     crs=str(tile.crs),
                     resolution=tile.resolution[::-1],
                     offset=tile.transform * (0, 0),
                     nodata=-999)
    assert mm.gbox == tile

    def _read(gbox,
              resampling='nearest',
              fallback_nodata=None,
              dst_nodata=-999):
        with RasterFileDataSource(mm.path, 1,
                                  nodata=fallback_nodata).open() as rdr:
            yy = np.full(gbox.shape, dst_nodata, dtype=rdr.dtype)
            roi = read_time_slice(rdr, yy, gbox, resampling, dst_nodata)
            return yy, roi

    gbox = gbx.pad(mm.gbox, 10)
    gbox = gbx.zoom_out(gbox, 0.873)
    yy, roi = _read(gbox)

    assert roi[0].start > 0 and roi[1].start > 0
    assert (yy[0] == -999).all()

    yy_expect, _ = rio_slurp(mm.path, gbox)
    np.testing.assert_array_equal(yy, yy_expect)

    gbox = gbx.zoom_out(mm.gbox[3:-3, 10:-10], 2.1)
    yy, roi = _read(gbox)

    assert roi_shape(roi) == gbox.shape
    assert not (yy == -999).any()

    gbox = GeoBox.from_geopolygon(mm.gbox.extent.to_crs(epsg3857).buffer(50),
                                  resolution=mm.gbox.resolution)

    assert gbox.extent.contains(mm.gbox.extent.to_crs(epsg3857))
    assert gbox.crs != mm.gbox.crs
    yy, roi = _read(gbox)
    assert roi[0].start > 0 and roi[1].start > 0
    assert (yy[0] == -999).all()

    gbox = gbx.zoom_out(gbox, 4)
    yy, roi = _read(gbox, resampling='average')
    nvalid = (yy != -999).sum()
    nempty = (yy == -999).sum()
    assert nvalid > nempty
示例#2
0
def gbox_reproject(
    geobox: GeoBox,
    crs: SomeCRS,
    resolution: Optional[Tuple[int, int]] = None,
    pad: int = 0,
    pad_wh: Union[int, Tuple[int, int]] = 16,
) -> GeoBox:
    """
    Compute GeoBox in a given projection that fully encloses footprint of the source GeoBox.

    :param geobox: Source GeoBox

    :param crs: CRS of the output GeoBox

    :param resolution: Desired output resolution (defaults to source
                       resolution, if source and destination projections share
                       common units)

    :param pad: Padding in pixels of output GeoBox

    :param pad_wh: Expand output GeoBox some more such that (W%pad_wh) == 0 and (H%pad_wh) == 0
    """
    from datacube.utils.geometry import gbox

    crs = _norm_crs_or_error(crs)

    if resolution is None:
        if geobox.crs.units == crs.units:
            resolution = geobox.resolution
        else:
            raise NotImplementedError(
                "Source and destination projections have different units: have to supply desired output resolution"
            )

    out = GeoBox.from_geopolygon(geobox.extent, resolution, crs)
    if pad > 0:
        out = gbox.pad(out, pad)
    if pad_wh:
        if isinstance(pad_wh, int):
            pad_wh = max(1, pad_wh)
            pad_wh = (pad_wh, pad_wh)
        out = gbox.pad_wh(out, *pad_wh)

    return out
示例#3
0
def _load_with_native_transform_1(
    sources: xr.DataArray,
    bands: Tuple[str, ...],
    geobox: GeoBox,
    native_transform: Callable[[xr.Dataset], xr.Dataset],
    basis: Optional[str] = None,
    groupby: Optional[str] = None,
    fuser: Optional[Callable[[xr.Dataset], xr.Dataset]] = None,
    resampling: str = "nearest",
    chunks: Optional[Dict[str, int]] = None,
    load_chunks: Optional[Dict[str, int]] = None,
    pad: Optional[int] = None,
) -> xr.Dataset:
    if basis is None:
        basis = bands[0]

    if load_chunks is None:
        load_chunks = chunks

    (ds, ) = sources.data[0]
    load_geobox = compute_native_load_geobox(geobox, ds, basis)
    if pad is not None:
        load_geobox = gbox.pad(load_geobox, pad)

    mm = ds.type.lookup_measurements(bands)
    xx = Datacube.load_data(sources, load_geobox, mm, dask_chunks=load_chunks)
    xx = native_transform(xx)

    if groupby is not None:
        if fuser is None:
            fuser = _nodata_fuser  # type: ignore
        xx = xx.groupby(groupby).map(fuser)

    _chunks = None
    if chunks is not None:
        _chunks = tuple(chunks.get(ax, -1) for ax in ("y", "x"))

    return xr_reproject(xx, geobox, chunks=_chunks,
                        resampling=resampling)  # type: ignore
def test_can_paste():
    src = AlbersGS.tile_geobox((17, -40))

    def check_true(dst, **kwargs):
        ok, reason = can_paste(compute_reproject_roi(src, dst), **kwargs)
        if not ok:
            assert ok is True, reason

    def check_false(dst, **kwargs):
        ok, reason = can_paste(compute_reproject_roi(src, dst), **kwargs)
        if ok:
            assert ok is False, "Expected can_paste to return False, but got True"

    check_true(gbx.pad(src, 100))
    check_true(src[:10, :10])
    check_true(gbx.translate_pix(src, 0.1, 0.3), ttol=0.5)
    check_true(gbx.translate_pix(src, 3, -4))
    check_true(gbx.flipx(src))
    check_true(gbx.flipy(src))
    check_true(gbx.flipx(gbx.flipy(src)))
    check_true(gbx.zoom_out(src, 2))
    check_true(gbx.zoom_out(src, 4))
    check_true(gbx.zoom_out(src[:9, :9], 3))

    # Check False code paths
    dst = GeoBox.from_geopolygon(src.extent.to_crs(epsg3857).buffer(10),
                                 resolution=src.resolution)
    check_false(dst)  # non ST
    check_false(gbx.affine_transform_pix(src, Affine.rotation(1)))  # non ST

    check_false(gbx.zoom_out(src, 1.9))  # non integer scale
    check_false(gbx.affine_transform_pix(src, Affine.scale(1, 2)))  # sx != sy

    dst = gbx.translate_pix(src, -1, -1)
    dst = gbx.zoom_out(dst, 2)
    check_false(dst)  # src_roi doesn't align for scale

    check_false(dst, stol=0.7)  # src_roi/scale != dst_roi
    check_false(gbx.translate_pix(src, 0.3, 0.4))  # sub-pixel translation
示例#5
0
def test_gbox_ops():
    s = GeoBox(1000, 100, Affine(10, 0, 12340, 0, -10, 316770), epsg3857)
    assert s.shape == (100, 1000)

    d = gbx.flipy(s)
    assert d.shape == s.shape
    assert d.crs is s.crs
    assert d.resolution == (-s.resolution[0], s.resolution[1])
    assert d.extent.contains(s.extent)
    with pytest.raises(ValueError):
        # flipped grid
        (s | d)
    with pytest.raises(ValueError):
        # flipped grid
        (s & d)

    d = gbx.flipx(s)
    assert d.shape == s.shape
    assert d.crs is s.crs
    assert d.resolution == (s.resolution[0], -s.resolution[1])
    assert d.extent.contains(s.extent)

    assert gbx.flipy(gbx.flipy(s)).affine == s.affine
    assert gbx.flipx(gbx.flipx(s)).affine == s.affine

    d = gbx.zoom_out(s, 2)
    assert d.shape == (50, 500)
    assert d.crs is s.crs
    assert d.extent.contains(s.extent)
    assert d.resolution == (s.resolution[0]*2, s.resolution[1]*2)

    d = gbx.zoom_out(s, 2*max(s.shape))
    assert d.shape == (1, 1)
    assert d.crs is s.crs
    assert d.extent.contains(s.extent)

    d = gbx.zoom_out(s, 1.33719)
    assert d.crs is s.crs
    assert d.extent.contains(s.extent)
    assert all(ds < ss for ds, ss in zip(d.shape, s.shape))
    with pytest.raises(ValueError):
        # lower resolution grid
        (s | d)
    with pytest.raises(ValueError):
        # lower resolution grid
        (s & d)

    d = gbx.zoom_to(s, s.shape)
    assert d == s

    d = gbx.zoom_to(s, (1, 3))
    assert d.shape == (1, 3)
    assert d.extent == s.extent

    d = gbx.zoom_to(s, (10000, 10000))
    assert d.shape == (10000, 10000)
    assert d.extent == s.extent

    d = gbx.pad(s, 1)
    assert d.crs is s.crs
    assert d.resolution == s.resolution
    assert d.extent.contains(s.extent)
    assert s.extent.contains(d.extent) is False
    assert d[1:-1, 1:-1].affine == s.affine
    assert d[1:-1, 1:-1].shape == s.shape
    assert d == (s | d)
    assert s == (s & d)

    d = gbx.pad_wh(s, 10)
    assert d == s

    d = gbx.pad_wh(s, 100, 8)
    assert d.width == s.width
    assert d.height % 8 == 0
    assert 0 < d.height - s.height < 8
    assert d.affine == s.affine
    assert d.crs is s.crs

    d = gbx.pad_wh(s, 13, 17)
    assert d.affine == s.affine
    assert d.crs is s.crs
    assert d.height % 17 == 0
    assert d.width % 13 == 0
    assert 0 < d.height - s.height < 17
    assert 0 < d.width - s.width < 13

    d = gbx.translate_pix(s, 1, 2)
    assert d.crs is s.crs
    assert d.resolution == s.resolution
    assert d.extent != s.extent
    assert s[2:3, 1:2].extent == d[:1, :1].extent

    d = gbx.translate_pix(s, -10, -2)
    assert d.crs is s.crs
    assert d.resolution == s.resolution
    assert d.extent != s.extent
    assert s[:1, :1].extent == d[2:3, 10:11].extent

    d = gbx.translate_pix(s, 0.1, 0)
    assert d.crs is s.crs
    assert d.shape == s.shape
    assert d.resolution == s.resolution
    assert d.extent != s.extent
    assert d.extent.contains(s[:, 1:].extent)

    d = gbx.translate_pix(s, 0, -0.5)
    assert d.crs is s.crs
    assert d.shape == s.shape
    assert d.resolution == s.resolution
    assert d.extent != s.extent
    assert s.extent.contains(d[1:, :].extent)

    d = gbx.affine_transform_pix(s, Affine(1, 0, 0,
                                           0, 1, 0))
    assert d.crs is s.crs
    assert d.shape == s.shape
    assert d.resolution == s.resolution
    assert d.extent == s.extent

    d = gbx.rotate(s, 180)
    assert d.crs is s.crs
    assert d.shape == s.shape
    assert d.extent != s.extent
    np.testing.assert_almost_equal(d.extent.area, s.extent.area, 1e-5)
    assert s[49:52, 499:502].extent.contains(d[50:51, 500:501].extent), "Check that center pixel hasn't moved"
示例#6
0
def test_gbox_ops():
    s = GeoBox(1000, 100, Affine(10, 0, 12340, 0, -10, 316770), epsg3857)
    assert s.shape == (100, 1000)

    d = gbx.flipy(s)
    assert d.shape == s.shape
    assert d.crs is s.crs
    assert d.resolution == (-s.resolution[0], s.resolution[1])
    assert d.extent.contains(s.extent)

    d = gbx.flipx(s)
    assert d.shape == s.shape
    assert d.crs is s.crs
    assert d.resolution == (s.resolution[0], -s.resolution[1])
    assert d.extent.contains(s.extent)

    assert gbx.flipy(gbx.flipy(s)).affine == s.affine
    assert gbx.flipx(gbx.flipx(s)).affine == s.affine

    d = gbx.zoom_out(s, 2)
    assert d.shape == (50, 500)
    assert d.crs is s.crs
    assert d.extent.contains(s.extent)
    assert d.resolution == (s.resolution[0] * 2, s.resolution[1] * 2)

    d = gbx.zoom_out(s, 2 * max(s.shape))
    assert d.shape == (1, 1)
    assert d.crs is s.crs
    assert d.extent.contains(s.extent)

    d = gbx.zoom_out(s, 1.33719)
    assert d.crs is s.crs
    assert d.extent.contains(s.extent)
    assert all(ds < ss for ds, ss in zip(d.shape, s.shape))

    d = gbx.zoom_to(s, s.shape)
    assert d == s

    d = gbx.zoom_to(s, (1, 3))
    assert d.shape == (1, 3)
    assert d.extent == s.extent

    d = gbx.zoom_to(s, (10000, 10000))
    assert d.shape == (10000, 10000)
    assert d.extent == s.extent

    d = gbx.pad(s, 1)
    assert d.crs is s.crs
    assert d.resolution == s.resolution
    assert d.extent.contains(s.extent)
    assert s.extent.contains(d.extent) is False
    assert d[1:-1, 1:-1].affine == s.affine
    assert d[1:-1, 1:-1].shape == s.shape

    d = gbx.translate_pix(s, 1, 2)
    assert d.crs is s.crs
    assert d.resolution == s.resolution
    assert d.extent != s.extent
    assert s[2:3, 1:2].extent == d[:1, :1].extent

    d = gbx.translate_pix(s, -10, -2)
    assert d.crs is s.crs
    assert d.resolution == s.resolution
    assert d.extent != s.extent
    assert s[:1, :1].extent == d[2:3, 10:11].extent

    d = gbx.translate_pix(s, 0.1, 0)
    assert d.crs is s.crs
    assert d.shape == s.shape
    assert d.resolution == s.resolution
    assert d.extent != s.extent
    assert d.extent.contains(s[:, 1:].extent)

    d = gbx.translate_pix(s, 0, -0.5)
    assert d.crs is s.crs
    assert d.shape == s.shape
    assert d.resolution == s.resolution
    assert d.extent != s.extent
    assert s.extent.contains(d[1:, :].extent)

    d = gbx.affine_transform_pix(s, Affine(1, 0, 0, 0, 1, 0))
    assert d.crs is s.crs
    assert d.shape == s.shape
    assert d.resolution == s.resolution
    assert d.extent == s.extent

    d = gbx.affine_transform_pix(s, Affine.rotation(10))
    assert d.crs is s.crs
    assert d.shape == s.shape
    assert d.extent != s.extent

    for deg in (33, -33, 20, 90, 180):
        d = gbx.rotate(s, 33)
        assert d.crs is s.crs
        assert d.shape == s.shape
        assert d.extent != s.extent
        np.testing.assert_almost_equal(d.extent.area, s.extent.area, 1e-5)
        assert s[49:52, 499:502].extent.contains(
            d[50:51, 500:501].extent), "Check that center pixel hasn't moved"