mirror of
https://github.com/rasterio/rasterio.git
synced 2025-12-08 17:36:12 +00:00
208 lines
6.8 KiB
Python
208 lines
6.8 KiB
Python
"""Tests for ``$ rio shapes``."""
|
|
|
|
|
|
import json
|
|
import re
|
|
|
|
import numpy as np
|
|
import pytest
|
|
|
|
import rasterio
|
|
from rasterio.rio.main import main_group
|
|
|
|
|
|
DEFAULT_SHAPE = (10, 10)
|
|
|
|
|
|
def bbox(*args):
|
|
return ' '.join([str(x) for x in args])
|
|
|
|
|
|
def test_shapes(runner, pixelated_image_file):
|
|
with pytest.warns(None):
|
|
|
|
result = runner.invoke(main_group, ['shapes', '--collection', pixelated_image_file])
|
|
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('"Feature"') == 4
|
|
assert np.allclose(
|
|
json.loads(result.output)['features'][0]['geometry']['coordinates'],
|
|
[[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]])
|
|
|
|
|
|
def test_shapes_invalid_bidx(runner, pixelated_image_file):
|
|
result = runner.invoke(
|
|
main_group, ['shapes', '--collection', pixelated_image_file, '--bidx', 4])
|
|
|
|
assert result.exit_code == 1
|
|
# Underlying exception message trapped by shapes
|
|
|
|
|
|
def test_shapes_sequence(runner, pixelated_image_file):
|
|
"""
|
|
--sequence option should produce 4 features in series rather than
|
|
inside a feature collection.
|
|
"""
|
|
with pytest.warns(None):
|
|
|
|
result = runner.invoke(
|
|
main_group, ['shapes', '--collection', pixelated_image_file, '--sequence'])
|
|
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 0
|
|
assert result.output.count('"Feature"') == 4
|
|
assert result.output.count('\n') == 4
|
|
|
|
|
|
def test_shapes_sequence_rs(runner, pixelated_image_file):
|
|
""" --rs option should use the feature separator character. """
|
|
|
|
result = runner.invoke(
|
|
main_group, ['shapes', '--collection', pixelated_image_file, '--sequence', '--rs'])
|
|
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 0
|
|
assert result.output.count('"Feature"') == 4
|
|
assert result.output.count(u'\u001e') == 4
|
|
|
|
|
|
def test_shapes_with_nodata(runner, pixelated_image, pixelated_image_file):
|
|
"""
|
|
An area of nodata should also be represented with a shape when using
|
|
--with-nodata option
|
|
"""
|
|
|
|
pixelated_image[0:2, 8:10] = 255
|
|
|
|
with rasterio.open(pixelated_image_file, 'r+') as out:
|
|
out.write(pixelated_image, indexes=1)
|
|
|
|
result = runner.invoke(
|
|
main_group, ['shapes', '--collection', pixelated_image_file, '--with-nodata'])
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('"Feature"') == 5
|
|
|
|
|
|
def test_shapes_indent(runner, pixelated_image_file):
|
|
"""
|
|
--indent option should produce lots of newlines and contiguous spaces
|
|
"""
|
|
with pytest.warns(None):
|
|
|
|
result = runner.invoke(
|
|
main_group, ['shapes', '--collection', pixelated_image_file, '--indent', 2])
|
|
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('"Feature"') == 4
|
|
assert result.output.count('\n') == 231
|
|
assert result.output.count(' ') == 180
|
|
|
|
|
|
def test_shapes_compact(runner, pixelated_image_file):
|
|
with pytest.warns(None):
|
|
|
|
result = runner.invoke(
|
|
main_group, ['shapes', '--collection', pixelated_image_file, '--compact'])
|
|
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('"Feature"') == 4
|
|
assert result.output.count(', ') == 0
|
|
assert result.output.count(': ') == 0
|
|
|
|
|
|
def test_shapes_sampling(runner, pixelated_image_file):
|
|
""" --sampling option should remove the single pixel features """
|
|
result = runner.invoke(
|
|
main_group, ['shapes', '--collection', pixelated_image_file, '--sampling', 2])
|
|
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('"Feature"') == 2
|
|
|
|
|
|
def test_shapes_precision(runner, pixelated_image_file):
|
|
""" Output numbers should have no more than 1 decimal place """
|
|
|
|
result = runner.invoke(
|
|
main_group, ['shapes', '--collection', pixelated_image_file, '--precision', 1])
|
|
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('"Feature"') == 4
|
|
assert re.search(r'\s\d*\.\d{2,}', result.output) is None
|
|
|
|
|
|
def test_shapes_mask(runner, pixelated_image, pixelated_image_file):
|
|
""" --mask should extract the nodata area of the image """
|
|
|
|
pixelated_image[0:5, 0:10] = 255
|
|
pixelated_image[0:10, 0:3] = 255
|
|
pixelated_image[8:10, 8:10] = 255
|
|
|
|
with rasterio.open(pixelated_image_file, 'r+') as out:
|
|
out.write(pixelated_image, indexes=1)
|
|
|
|
with pytest.warns(None):
|
|
result = runner.invoke(
|
|
main_group, ['shapes', '--collection', pixelated_image_file, '--mask'])
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('"Feature"') == 1
|
|
assert np.allclose(
|
|
json.loads(result.output)['features'][0]['geometry']['coordinates'],
|
|
[[[3, 5], [3, 10], [8, 10], [8, 8], [9, 8], [10, 8], [10, 5], [3, 5]]])
|
|
|
|
|
|
def test_shapes_mask_sampling(runner, pixelated_image, pixelated_image_file):
|
|
"""using --sampling with the mask should snap coordinates to the nearest
|
|
factor of 5
|
|
"""
|
|
pixelated_image[0:5, 0:10] = 255
|
|
pixelated_image[0:10, 0:3] = 255
|
|
pixelated_image[8:10, 8:10] = 255
|
|
|
|
with rasterio.open(pixelated_image_file, 'r+') as out:
|
|
out.write(pixelated_image, indexes=1)
|
|
|
|
with pytest.warns(None):
|
|
|
|
result = runner.invoke(
|
|
main_group,
|
|
['shapes', '--collection', pixelated_image_file, '--mask', '--sampling', 5])
|
|
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('"Feature"') == 1
|
|
|
|
assert np.allclose(
|
|
json.loads(result.output)['features'][0]['geometry']['coordinates'],
|
|
[[[5, 5], [5, 10], [10, 10], [10, 5], [5, 5]]])
|
|
|
|
|
|
def test_shapes_band1_as_mask(runner, pixelated_image, pixelated_image_file):
|
|
"""
|
|
When using --as-mask option, pixel value should not matter, only depends
|
|
on pixels being contiguous.
|
|
"""
|
|
|
|
pixelated_image[2:3, 2:3] = 4
|
|
|
|
with rasterio.open(pixelated_image_file, 'r+') as out:
|
|
out.write(pixelated_image, indexes=1)
|
|
|
|
with pytest.warns(None):
|
|
result = runner.invoke(
|
|
main_group,
|
|
['shapes', '--collection', pixelated_image_file, '--band', '--bidx', '1', '--as-mask'])
|
|
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('"Feature"') == 3
|
|
assert np.allclose(
|
|
json.loads(result.output)['features'][1]['geometry']['coordinates'],
|
|
[[[2, 2], [2, 5], [5, 5], [5, 2], [2, 2]]])
|