mirror of
https://github.com/rasterio/rasterio.git
synced 2025-12-08 17:36:12 +00:00
344 lines
11 KiB
Python
344 lines
11 KiB
Python
import logging
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
import click
|
|
from click.testing import CliRunner
|
|
|
|
import rasterio
|
|
from rasterio.rio import features
|
|
|
|
|
|
# logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
|
|
|
|
TEST_FEATURES = """{
|
|
"geometry": {
|
|
"coordinates": [
|
|
[
|
|
[-110, 40],
|
|
[-100, 40],
|
|
[-100, 45],
|
|
[-105, 45],
|
|
[-110, 40]
|
|
]
|
|
],
|
|
"type": "Polygon"
|
|
},
|
|
"properties": {
|
|
"val": 15
|
|
},
|
|
"type": "Feature"
|
|
}"""
|
|
|
|
|
|
# > rio shapes tests/data/shade.tif --mask --sampling 500 --projected --precision 0
|
|
TEST_MERC_FEATURECOLLECTION = """{
|
|
"bbox": [-11858135.0, 4803914.0, -11848351.0, 4813698.0],
|
|
"features": [{
|
|
"bbox": [-11853357.504145855, 4808920.97837715,
|
|
-11848580.189878704, 4813698.2926443005],
|
|
"geometry": {
|
|
"coordinates": [
|
|
[
|
|
[-11853357.504145855, 4813698.2926443005],
|
|
[-11853357.504145855, 4808920.97837715],
|
|
[-11848580.189878704, 4808920.97837715],
|
|
[-11848580.189878704, 4813698.2926443005],
|
|
[-11853357.504145855, 4813698.2926443005]
|
|
]
|
|
],
|
|
"type": "Polygon"
|
|
},
|
|
"properties": {
|
|
"val": 2
|
|
},
|
|
"type": "Feature"
|
|
}, {
|
|
"bbox": [-11858134.818413004, 4804143.66411,
|
|
-11853357.504145855, 4808920.97837715],
|
|
"geometry": {
|
|
"coordinates": [
|
|
[
|
|
[-11858134.818413004, 4808920.97837715],
|
|
[-11858134.818413004, 4804143.66411],
|
|
[-11853357.504145855, 4804143.66411],
|
|
[-11853357.504145855, 4808920.97837715],
|
|
[-11858134.818413004, 4808920.97837715]
|
|
]
|
|
],
|
|
"type": "Polygon"
|
|
},
|
|
"properties": {
|
|
"val": 3
|
|
},
|
|
"type": "Feature"
|
|
}],
|
|
"type": "FeatureCollection"
|
|
}"""
|
|
|
|
|
|
def test_err():
|
|
runner = CliRunner()
|
|
result = runner.invoke(
|
|
features.shapes, ['tests/data/shade.tif', '--bidx', '4'])
|
|
assert result.exit_code == 1
|
|
|
|
|
|
def test_shapes(runner):
|
|
result = runner.invoke(features.shapes, ['tests/data/shade.tif'])
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('"Feature"') == 232
|
|
|
|
|
|
def test_shapes_sequence(runner):
|
|
result = runner.invoke(features.shapes, ['tests/data/shade.tif', '--sequence'])
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 0
|
|
assert result.output.count('"Feature"') == 232
|
|
|
|
|
|
def test_shapes_sequence_rs(runner):
|
|
result = runner.invoke(
|
|
features.shapes, [
|
|
'tests/data/shade.tif',
|
|
'--sequence',
|
|
'--rs'])
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 0
|
|
assert result.output.count('"Feature"') == 232
|
|
assert result.output.count(u'\u001e') == 232
|
|
|
|
|
|
def test_shapes_with_nodata(runner):
|
|
result = runner.invoke(features.shapes, ['tests/data/shade.tif', '--with-nodata'])
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('"Feature"') == 288
|
|
|
|
|
|
def test_shapes_indent(runner):
|
|
result = runner.invoke(features.shapes, ['tests/data/shade.tif', '--indent', '2'])
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('\n') == 70139
|
|
|
|
|
|
def test_shapes_compact(runner):
|
|
result = runner.invoke(features.shapes, ['tests/data/shade.tif', '--compact'])
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count(', ') == 0
|
|
assert result.output.count(': ') == 0
|
|
|
|
|
|
def test_shapes_sampling(runner):
|
|
result = runner.invoke(
|
|
features.shapes, ['tests/data/shade.tif', '--sampling', '10'])
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('"Feature"') == 124
|
|
|
|
|
|
def test_shapes_precision(runner):
|
|
result = runner.invoke(
|
|
features.shapes, ['tests/data/shade.tif', '--precision', '1'])
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
# Find no numbers with 2+ decimal places.
|
|
assert re.search(r'\d*\.\d{2,}', result.output) is None
|
|
|
|
|
|
def test_shapes_mask(runner):
|
|
result = runner.invoke(features.shapes, ['tests/data/RGB.byte.tif', '--mask'])
|
|
assert result.exit_code == 0
|
|
assert result.output.count('"FeatureCollection"') == 1
|
|
assert result.output.count('"Feature"') == 9
|
|
|
|
|
|
def test_rasterize_err(tmpdir, runner):
|
|
output = str(tmpdir.join('test.tif'))
|
|
# Test invalid stdin
|
|
result = runner.invoke(features.rasterize, [output], input='BOGUS')
|
|
assert result.exit_code == -1
|
|
|
|
# Test invalid GeoJSON
|
|
result = runner.invoke(features.rasterize, [output],
|
|
input='{"foo": "bar"}')
|
|
assert result.exit_code == 2
|
|
|
|
# Test invalid res
|
|
result = runner.invoke(features.rasterize, [output], input=TEST_FEATURES)
|
|
assert result.exit_code == 2
|
|
|
|
# Test invalid CRS for bounds
|
|
result = runner.invoke(features.rasterize, [output, '--res', 1],
|
|
input=TEST_MERC_FEATURECOLLECTION)
|
|
assert result.exit_code == 2
|
|
|
|
# Test invalid CRS value
|
|
result = runner.invoke(features.rasterize, [output,
|
|
'--res', 1,
|
|
'--src_crs', 'BOGUS'],
|
|
input=TEST_MERC_FEATURECOLLECTION)
|
|
assert result.exit_code == 2
|
|
|
|
|
|
def test_rasterize(tmpdir, runner):
|
|
# Test dimensions
|
|
output = str(tmpdir.join('test.tif'))
|
|
result = runner.invoke(features.rasterize,
|
|
[output, '--dimensions', 20, 10],
|
|
input=TEST_FEATURES)
|
|
assert result.exit_code == 0
|
|
assert os.path.exists(output)
|
|
with rasterio.open(output) as out:
|
|
assert out.count == 1
|
|
assert out.meta['width'] == 20
|
|
assert out.meta['height'] == 10
|
|
data = out.read_band(1, masked=False)
|
|
assert (data == 0).sum() == 55
|
|
assert (data == 1).sum() == 145
|
|
|
|
# Test dimensions and bounds
|
|
output = str(tmpdir.join('test2.tif'))
|
|
result = runner.invoke(features.rasterize,
|
|
[output,
|
|
'--dimensions', 40, 20,
|
|
'--bounds', -120, 30, -90, 50
|
|
], input=TEST_FEATURES)
|
|
assert result.exit_code == 0
|
|
assert os.path.exists(output)
|
|
with rasterio.open(output) as out:
|
|
assert out.count == 1
|
|
assert out.meta['width'] == 40
|
|
assert out.meta['height'] == 20
|
|
data = out.read_band(1, masked=False)
|
|
assert (data == 0).sum() == 748
|
|
assert (data == 1).sum() == 52
|
|
|
|
# Test resolution
|
|
output = str(tmpdir.join('test3.tif'))
|
|
result = runner.invoke(features.rasterize,
|
|
[output, '--res', 0.5], input=TEST_FEATURES)
|
|
assert result.exit_code == 0
|
|
assert os.path.exists(output)
|
|
with rasterio.open(output) as out:
|
|
assert out.count == 1
|
|
assert out.meta['width'] == 20
|
|
assert out.meta['height'] == 10
|
|
data = out.read_band(1, masked=False)
|
|
assert (data == 0).sum() == 55
|
|
assert (data == 1).sum() == 145
|
|
|
|
|
|
def test_rasterize_existing_output(tmpdir, runner):
|
|
output = str(tmpdir.join('test.tif'))
|
|
result = runner.invoke(features.rasterize,
|
|
[output, '--res', 0.5], input=TEST_FEATURES)
|
|
assert result.exit_code == 0
|
|
assert os.path.exists(output)
|
|
|
|
geojson = """{
|
|
"geometry": {
|
|
"coordinates": [
|
|
[
|
|
[-102, 40],
|
|
[-98, 40],
|
|
[-98, 45],
|
|
[-100, 45],
|
|
[-102, 40]
|
|
]
|
|
],
|
|
"type": "Polygon"
|
|
},
|
|
"type": "Feature"
|
|
}"""
|
|
|
|
result = runner.invoke(features.rasterize, [output, '--default_value', 2],
|
|
input=geojson)
|
|
|
|
with rasterio.open(output) as out:
|
|
assert out.count == 1
|
|
data = out.read_band(1, masked=False)
|
|
assert (data == 0).sum() == 55
|
|
assert (data == 1).sum() == 125
|
|
assert (data == 2).sum() == 20
|
|
|
|
|
|
def test_rasterize_like(tmpdir, runner):
|
|
output = str(tmpdir.join('test.tif'))
|
|
result = runner.invoke(features.rasterize,
|
|
[output, '--like', 'tests/data/shade.tif'],
|
|
input=TEST_MERC_FEATURECOLLECTION)
|
|
assert result.exit_code == 0
|
|
assert os.path.exists(output)
|
|
with rasterio.open(output) as out:
|
|
assert out.count == 1
|
|
data = out.read_band(1, masked=False)
|
|
assert (data == 0).sum() == 548576
|
|
assert (data == 1).sum() == 500000
|
|
|
|
# Test invalid like raster
|
|
output = str(tmpdir.join('test2.tif'))
|
|
result = runner.invoke(features.rasterize,
|
|
[output, '--like', 'foo.tif'], input=TEST_FEATURES)
|
|
assert result.exit_code == 2
|
|
|
|
|
|
def test_rasterize_property_value(tmpdir, runner):
|
|
# Test feature collection property values
|
|
output = str(tmpdir.join('test.tif'))
|
|
result = runner.invoke(features.rasterize,
|
|
[output,
|
|
'--res', 1000,
|
|
'--property', 'val',
|
|
'--src_crs', 'EPSG:3857'
|
|
],
|
|
input=TEST_MERC_FEATURECOLLECTION)
|
|
assert result.exit_code == 0
|
|
assert os.path.exists(output)
|
|
with rasterio.open(output) as out:
|
|
assert out.count == 1
|
|
data = out.read_band(1, masked=False)
|
|
assert (data == 0).sum() == 50
|
|
assert (data == 2).sum() == 25
|
|
assert (data == 3).sum() == 25
|
|
|
|
# Test feature property values
|
|
output = str(tmpdir.join('test2.tif'))
|
|
result = runner.invoke(features.rasterize,
|
|
[output, '--res', 0.5, '--property', 'val'],
|
|
input=TEST_FEATURES)
|
|
assert result.exit_code == 0
|
|
assert os.path.exists(output)
|
|
with rasterio.open(output) as out:
|
|
assert out.count == 1
|
|
data = out.read_band(1, masked=False)
|
|
assert (data == 0).sum() == 55
|
|
assert (data == 15).sum() == 145
|
|
|
|
def test_rasterize_out_of_bounds(tmpdir, runner):
|
|
output = str(tmpdir.join('test.tif'))
|
|
|
|
# Test out of bounds of --like raster
|
|
result = runner.invoke(features.rasterize,
|
|
[output, '--like', 'tests/data/shade.tif'],
|
|
input=TEST_FEATURES)
|
|
assert result.exit_code == 2
|
|
|
|
# Test out of bounds of existing output raster (first have to create one)
|
|
result = runner.invoke(features.rasterize,
|
|
[output,
|
|
'--res', 1000,
|
|
'--property', 'val',
|
|
'--src_crs', 'EPSG:3857'
|
|
],
|
|
input=TEST_MERC_FEATURECOLLECTION)
|
|
assert result.exit_code == 0
|
|
assert os.path.exists(output)
|
|
|
|
result = runner.invoke(features.rasterize, [output], input=TEST_FEATURES)
|
|
assert result.exit_code == 2
|