rasterio/tests/test_features_shapes.py

144 lines
4.3 KiB
Python

import logging
import sys
import numpy
import pytest
import rasterio
import rasterio.features as ftrz
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
def test_shapes():
"""Test creation of shapes from pixel values"""
image = numpy.zeros((20, 20), dtype=rasterio.ubyte)
image[5:15, 5:15] = 127
with rasterio.drivers():
shapes = ftrz.shapes(image)
shape, val = next(shapes)
assert shape['type'] == 'Polygon'
assert len(shape['coordinates']) == 2 # exterior and hole
assert val == 0
shape, val = next(shapes)
assert shape['type'] == 'Polygon'
assert len(shape['coordinates']) == 1 # no hole
assert val == 127
try:
shape, val = next(shapes)
except StopIteration:
assert True
else:
assert False
def test_shapes_band_shortcut():
"""Test rasterio bands as input to shapes"""
with rasterio.drivers():
with rasterio.open('tests/data/shade.tif') as src:
shapes = ftrz.shapes(rasterio.band(src, 1))
shape, val = next(shapes)
assert shape['type'] == 'Polygon'
assert len(shape['coordinates']) == 1
assert val == 255
def test_shapes_internal_driver_manager():
"""Make sure this works if driver is managed outside this test"""
image = numpy.zeros((20, 20), dtype=rasterio.ubyte)
image[5:15, 5:15] = 127
shapes = ftrz.shapes(image)
shape, val = next(shapes)
assert shape['type'] == 'Polygon'
def test_shapes_connectivity():
"""Test connectivity options"""
image = numpy.zeros((20, 20), dtype=rasterio.ubyte)
image[5:11, 5:11] = 1
image[11, 11] = 1
shapes = ftrz.shapes(image, connectivity=4)
shape, val = next(shapes)
assert len(shape['coordinates'][0]) == 5
shapes = ftrz.shapes(image, connectivity=8)
shape, val = next(shapes)
assert len(shape['coordinates'][0]) == 9
# Note: geometry is not technically valid at this point, it has a self
# intersection at 11,11
# Test invalid connectivity
with pytest.raises(ValueError):
shapes = ftrz.shapes(image, connectivity=12)
next(shapes)
def test_shapes_dtype():
"""Test image data type handling"""
rows = cols = 10
with rasterio.drivers():
supported_types = (
('int16', -32768),
('int32', -2147483648),
('uint8', 255),
('uint16', 65535),
('float32', 1.434532)
)
for dtype, test_value in supported_types:
image = numpy.zeros((rows, cols), dtype=dtype)
image[2:5, 2:5] = test_value
shapes = ftrz.shapes(image)
shape, value = next(shapes)
if dtype == 'float32':
assert round(value, 6) == round(test_value, 6)
else:
assert value == test_value
# Unsupported types should all raise exceptions
unsupported_types = (
('int8', -127),
('uint32', 4294967295),
('int64', 20439845334323),
('float16', -9343.232),
('float64', -98332.133422114)
)
for dtype, test_value in unsupported_types:
with pytest.raises(ValueError):
image = numpy.zeros((rows, cols), dtype=dtype)
image[2:5, 2:5] = test_value
shapes = ftrz.shapes(image)
next(shapes)
# Test mask types
image = numpy.zeros((rows, cols), dtype='uint8')
image.fill(255)
supported_mask_types = (
('bool', 1),
('uint8', 255)
)
for dtype, mask_value in supported_mask_types:
mask = numpy.zeros((rows, cols), dtype=dtype)
mask[2:5, 2:5] = mask_value
shapes = ftrz.shapes(image, mask=mask)
shape, value = next(shapes)
assert value == 255
unsupported_mask_types = (
('int8', -127),
('int16', -32768)
)
for dtype, mask_value in unsupported_mask_types:
with pytest.raises(ValueError):
mask = numpy.zeros((rows, cols), dtype=dtype)
mask[2:5, 2:5] = mask_value
shapes = ftrz.shapes(image, mask=mask)
next(shapes)