import logging import sys import warnings import numpy as np import pytest import rasterio from rasterio.enums import MaskFlags from rasterio.errors import NodataShadowWarning, RasterioDeprecationWarning @pytest.fixture(scope='function') def tiffs(tmpdir): with rasterio.open('tests/data/RGB.byte.tif') as src: profile = src.profile shadowed_profile = profile.copy() shadowed_profile['count'] = 4 with rasterio.open( str(tmpdir.join('shadowed.tif')), 'w', **shadowed_profile) as dst: for i, band in enumerate(src.read(masked=False), 1): dst.write(band, i) dst.write(band, 4) del profile['nodata'] with rasterio.open( str(tmpdir.join('no-nodata.tif')), 'w', **profile) as dst: dst.write(src.read(masked=False)) with rasterio.open( str(tmpdir.join('sidecar-masked.tif')), 'w', **profile) as dst: dst.write(src.read(masked=False)) mask = np.zeros(src.shape, dtype='uint8') dst.write_mask(mask) return tmpdir def test_mask_flags(): with rasterio.open('tests/data/RGB.byte.tif') as src: for flags in src.mask_flag_enums: assert MaskFlags.nodata in flags assert MaskFlags.per_dataset not in flags assert MaskFlags.alpha not in flags def test_mask_flags_rgba(): with rasterio.open('tests/data/RGBA.byte.tif') as src: for flags in src.mask_flag_enums[:3]: assert MaskFlags.nodata not in flags assert MaskFlags.per_dataset in flags assert MaskFlags.alpha in flags assert [MaskFlags.all_valid] == src.mask_flag_enums[3] def test_mask_flags_sidecar(tiffs): filename = str(tiffs.join('sidecar-masked.tif')) with rasterio.open(filename) as src: for flags in src.mask_flag_enums: assert MaskFlags.nodata not in flags assert MaskFlags.alpha not in flags assert MaskFlags.per_dataset in flags def test_mask_flags_shadow(tiffs): filename = str(tiffs.join('shadowed.tif')) with rasterio.open(filename) as src: for flags in src.mask_flag_enums: assert MaskFlags.nodata in flags assert MaskFlags.alpha not in flags assert MaskFlags.per_dataset not in flags def test_warning_no(): """No shadow warning is raised""" with rasterio.open('tests/data/RGB.byte.tif') as src: try: rm, gm, bm = src.read_masks() except NodataShadowWarning: pytest.fail("Unexpected NodataShadowWarning raised") def test_warning_shadow(tiffs): """Shadow warning is raised""" filename = str(tiffs.join('shadowed.tif')) with rasterio.open(filename) as src: with pytest.warns(NodataShadowWarning): src.read_masks() def test_masks(): with rasterio.open('tests/data/RGB.byte.tif') as src: rm, gm, bm = src.read_masks() r, g, b = src.read(masked=False) assert not r[rm == 0].any() assert not g[gm == 0].any() assert not b[bm == 0].any() def test_masked_true(): with rasterio.open('tests/data/RGB.byte.tif') as src: r, g, b = src.read(masked=True) rm, gm, bm = src.read_masks() assert (r.mask == ~rm.astype('bool')).all() assert (g.mask == ~gm.astype('bool')).all() assert (b.mask == ~bm.astype('bool')).all() def test_masked_none(): with rasterio.open('tests/data/RGB.byte.tif') as src: r, g, b = src.read(masked=True) rm, gm, bm = src.read_masks() assert (r.mask == ~rm.astype('bool')).all() assert (g.mask == ~gm.astype('bool')).all() assert (b.mask == ~bm.astype('bool')).all() def test_masking_no_nodata(tiffs): # if the dataset has no defined nodata values, all data is # considered valid data. The GDAL masks bands are arrays of # 255 values. ``read()`` returns masked arrays where `mask` # is False. filename = str(tiffs.join('no-nodata.tif')) with rasterio.open(filename) as src: for flags in src.mask_flag_enums: assert MaskFlags.all_valid in flags assert MaskFlags.alpha not in flags assert MaskFlags.nodata not in flags rgb = src.read(masked=False) assert not hasattr(rgb, 'mask') r = src.read(1, masked=False) assert not hasattr(r, 'mask') rgb = src.read(masked=True) assert hasattr(rgb, 'mask') assert not rgb.mask.any() r = src.read(1, masked=True) assert hasattr(r, 'mask') assert not r.mask.any() rgb = src.read(masked=True) assert hasattr(rgb, 'mask') assert not r.mask.any() r = src.read(1, masked=True) assert not r.mask.any() masks = src.read_masks() assert masks.all() def test_masking_sidecar_mask(tiffs): # If the dataset has a .msk sidecar mask band file, all masks will # be derived from that file. with rasterio.open(str(tiffs.join('sidecar-masked.tif'))) as src: for flags in src.mask_flag_enums: assert MaskFlags.per_dataset in flags assert MaskFlags.alpha not in flags assert MaskFlags.nodata not in flags rgb = src.read(masked=True) assert rgb.mask.all() r = src.read(1, masked=True) assert r.mask.all() masks = src.read_masks() assert not masks.any()