def test_rasterio_nodata(tmpdir): from datacube.testutils.io import dc_read, write_gtiff from pathlib import Path roi = np.s_[10:20, 20:30] xx = np.zeros((64, 64), dtype='uint8') xx[roi] = 255 pp = Path(str(tmpdir)) mm = write_gtiff(pp/'absent_nodata.tiff', xx, nodata=None) yy = dc_read(mm.path, gbox=mm.gbox, fallback_nodata=None) np.testing.assert_array_equal(xx, yy) # fallback nodata is outside source range so it shouldn't be used yy = dc_read(mm.path, gbox=mm.gbox, fallback_nodata=-1, dst_nodata=-999, dtype='int16') np.testing.assert_array_equal(xx.astype('int16'), yy) # treat zeros as no-data + type conversion while reading yy_expect = xx.copy().astype('int16') yy_expect[xx == 0] = -999 assert set(yy_expect.ravel()) == {-999, 255} yy = dc_read(mm.path, fallback_nodata=0, dst_nodata=-999, dtype='int16') np.testing.assert_array_equal(yy_expect, yy) # now check that file nodata is used instead of fallback mm = write_gtiff(pp/'with_nodata.tiff', xx, nodata=33) yy = dc_read(mm.path, fallback_nodata=0, dst_nodata=-999, dtype='int16') np.testing.assert_array_equal(xx, yy) yy = dc_read(mm.path) np.testing.assert_array_equal(xx, yy)
def test_rio_slurp(tmpdir): w, h, dtype, nodata, ndw = 96, 64, 'int16', -999, 7 pp = Path(str(tmpdir)) aa = mk_test_image(w, h, dtype, nodata, nodata_width=ndw) assert aa.shape == (h, w) assert aa.dtype.name == dtype assert aa[10, 30] == (30 << 8) | 10 assert aa[10, 11] == nodata aa0 = aa.copy() mm0 = write_gtiff(pp / "rio-slurp-aa.tif", aa, nodata=-999, overwrite=True) mm00 = write_gtiff(pp / "rio-slurp-aa-missing-nodata.tif", aa, nodata=None, overwrite=True) aa, mm = rio_slurp(mm0.path) np.testing.assert_array_equal(aa, aa0) assert mm.gbox == mm0.gbox assert aa.shape == mm.gbox.shape aa, mm = rio_slurp(mm0.path, aa0.shape) np.testing.assert_array_equal(aa, aa0) assert aa.shape == mm.gbox.shape assert mm.gbox is mm.src_gbox aa, mm = rio_slurp(mm0.path, (3, 7)) assert aa.shape == (3, 7) assert aa.shape == mm.gbox.shape assert mm.gbox != mm.src_gbox assert mm.src_gbox == mm0.gbox assert mm.gbox.extent == mm0.gbox.extent aa, mm = rio_slurp(mm0.path, aa0.shape) np.testing.assert_array_equal(aa, aa0) assert aa.shape == mm.gbox.shape aa, mm = rio_slurp(mm0.path, mm0.gbox, resampling='nearest') np.testing.assert_array_equal(aa, aa0) aa, mm = rio_slurp(mm0.path, gbox=mm0.gbox, dtype='float32') assert aa.dtype == 'float32' np.testing.assert_array_equal(aa, aa0.astype('float32')) aa, mm = rio_slurp(mm0.path, mm0.gbox, dst_nodata=-33) np.testing.assert_array_equal(aa == -33, aa0 == -999) aa, mm = rio_slurp(mm00.path, mm00.gbox, dst_nodata=None) np.testing.assert_array_equal(aa, aa0)
def gen_tiff_dataset(bands, base_folder, prefix='', timestamp='2018-07-19', **kwargs): """ each band: .name - string .values - ndarray .nodata - numeric|None :returns: (Dataset, GeoBox) """ if not isinstance(bands, Sequence): bands = (bands, ) # write arrays to disk and construct compatible measurement definitions gbox = None mm = [] for band in bands: name = band.name fname = prefix + name + '.tiff' meta = write_gtiff(base_folder / fname, band.values, nodata=band.nodata, overwrite=True, **kwargs) gbox = meta.gbox mm.append(dict(name=name, path=fname, layer=1, dtype=meta.dtype)) uri = Path(base_folder / 'metadata.yaml').absolute().as_uri() ds = mk_sample_dataset(mm, uri=uri, timestamp=timestamp) return ds, gbox
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
def test_rio_slurp_with_gbox(tmpdir): w, h, dtype, nodata, ndw = 96, 64, 'int16', -999, 7 pp = Path(str(tmpdir)) aa = mk_test_image(w, h, dtype, nodata, nodata_width=ndw) assert aa.dtype.name == dtype assert aa[10, 30] == (30 << 8) | 10 assert aa[10, 11] == nodata aa = np.stack([aa, aa[::-1, ::-1]]) assert aa.shape == (2, h, w) aa0 = aa.copy() mm = write_gtiff(pp / "rio-slurp-aa.tif", aa, nodata=-999, overwrite=True) assert mm.count == 2 aa, mm = rio_slurp(mm.path, mm.gbox) assert aa.shape == aa0.shape np.testing.assert_array_equal(aa, aa0)
def test_testutils_gtif(tmpdir): from datacube.testutils import mk_test_image from datacube.testutils.io import write_gtiff, rio_slurp w, h, dtype, nodata, ndw = 96, 64, 'int16', -999, 7 aa = mk_test_image(w, h, dtype, nodata, nodata_width=ndw) bb = mk_test_image(w, h, dtype, nodata=None) assert aa.shape == (h, w) assert aa.dtype.name == dtype assert aa[10, 30] == (30 << 8) | 10 assert aa[10, 11] == nodata assert bb[10, 11] == (11 << 8) | 10 aa5 = np.stack((aa, ) * 5) fname = pathlib.Path(str(tmpdir / "aa.tiff")) fname5 = pathlib.Path(str(tmpdir / "aa5.tiff")) aa_meta = write_gtiff(fname, aa, nodata=nodata, blocksize=128, resolution=(100, -100), offset=(12300, 11100), overwrite=True) aa5_meta = write_gtiff(str(fname5), aa5, nodata=nodata, resolution=(100, -100), offset=(12300, 11100), overwrite=True) assert fname.exists() assert fname5.exists() assert aa_meta.gbox.shape == (h, w) assert aa_meta.path is fname aa_, aa_meta_ = rio_slurp(fname) aa5_, aa5_meta_ = rio_slurp(fname5) assert aa_meta_.path is fname (sx, _, tx, _, sy, ty, *_) = aa5_meta_.transform assert (tx, ty) == (12300, 11100) assert (sx, sy) == (100, -100) np.testing.assert_array_equal(aa, aa_) np.testing.assert_array_equal(aa5, aa5_) assert aa_meta_.transform == aa_meta.transform assert aa5_meta_.transform == aa5_meta.transform # check that overwrite is off by default with pytest.raises(IOError): write_gtiff(fname, aa, nodata=nodata, blocksize=128) # check that overwrite re-writes file write_gtiff(fname, bb[:32, :32], gbox=aa_meta.gbox[:32, :32], overwrite=True) bb_, mm = rio_slurp(fname, (32, 32)) np.testing.assert_array_equal(bb[:32, :32], bb_) assert mm.gbox == aa_meta.gbox[:32, :32] with pytest.raises(ValueError): write_gtiff(fname, np.zeros((3, 4, 5, 6)))
def test_read_paste(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() mm = write_gtiff(pp / 'tst-read-paste-128x64-int16.tif', xx, nodata=None) def _read(gbox, resampling='nearest', fallback_nodata=-999, dst_nodata=-999, check_paste=False): with RasterFileDataSource(mm.path, 1, nodata=fallback_nodata).open() as rdr: if check_paste: # check that we are using paste paste_ok, reason = can_paste( compute_reproject_roi(rdr_geobox(rdr), gbox)) assert paste_ok is True, reason yy = np.full(gbox.shape, dst_nodata, dtype=rdr.dtype) roi = read_time_slice(rdr, yy, gbox, resampling, dst_nodata) return yy, roi # read native whole yy, roi = _read(mm.gbox) np.testing.assert_array_equal(xx, yy) assert roi == np.s_[0:64, 0:128] # read native whole, no nodata case yy, roi = _read(mm.gbox, fallback_nodata=None) np.testing.assert_array_equal(xx, yy) assert roi == np.s_[0:64, 0:128] # read native whole, ignoring small sub-pixel translation yy, roi = _read(gbx.translate_pix(mm.gbox, 0.3, -0.4), fallback_nodata=-33) np.testing.assert_array_equal(xx, yy) assert roi == np.s_[0:64, 0:128] # no overlap between src and dst yy, roi = _read(gbx.translate_pix(mm.gbox, 10000, -10000)) assert roi_is_empty(roi) # read with Y flipped yy, roi = _read(gbx.flipy(mm.gbox)) np.testing.assert_array_equal(xx[::-1, :], yy) assert roi == np.s_[0:64, 0:128] # read with X flipped yy, roi = _read(gbx.flipx(mm.gbox)) np.testing.assert_array_equal(xx[:, ::-1], yy) assert roi == np.s_[0:64, 0:128] # read with X and Y flipped yy, roi = _read(gbx.flipy(gbx.flipx(mm.gbox))) assert roi == np.s_[0:64, 0:128] np.testing.assert_array_equal(xx[::-1, ::-1], yy[roi]) # dst is fully inside src sroi = np.s_[10:19, 31:47] yy, roi = _read(mm.gbox[sroi]) np.testing.assert_array_equal(xx[sroi], yy[roi]) # partial overlap yy, roi = _read(gbx.translate_pix(mm.gbox, -3, -10)) assert roi == np.s_[10:64, 3:128] np.testing.assert_array_equal(xx[:-10, :-3], yy[roi]) assert (yy[:10, :] == -999).all() assert (yy[:, :3] == -999).all() # scaling paste yy, roi = _read(gbx.zoom_out(mm.gbox, 2), check_paste=True) assert roi == np.s_[0:32, 0:64] np.testing.assert_array_equal(xx[1::2, 1::2], yy)