"""Unittests for $ rio blocks""" import json import re import numpy as np import rasterio from rasterio.warp import transform_bounds from rasterio.compat import zip_longest from rasterio.rio.main import main_group def check_features_block_windows(features, src, bidx): """Compare GeoJSON features to a datasource's blocks + windows. Parameters ---------- features : iter GeoJSON features src : a dataset object opened in 'r' mode Open input datasource Returns ------- bool ``True`` if the two block/window streams match and ``False`` otherwise """ out = [] iterator = zip_longest(features, src.block_windows(bidx=bidx)) for feat, (block, window) in iterator: out.append(np.array_equal( json.loads(feat['properties']['block']), block)) f_win = feat['properties']['window'] assert f_win['col_off'] == window.col_off assert f_win['row_off'] == window.row_off return all(out) def test_windows(runner, path_rgb_byte_tif): result = runner.invoke(main_group, [ 'blocks', path_rgb_byte_tif]) assert result.exit_code == 0 fc = json.loads(result.output) with rasterio.open(path_rgb_byte_tif) as src: block_windows = tuple(src.block_windows()) # Check the coordinates of the first output feature actual_first = fc['features'][0] expected_first = block_windows[0] bounds = src.window_bounds(expected_first[1]) xmin, ymin, xmax, ymax = transform_bounds(src.crs, 'EPSG:4326', *bounds) coordinates = [[xmin, ymin], [xmin, ymax], [xmax, ymax], [xmax, ymin]] assert np.array_equal( actual_first['geometry']['coordinates'][0], coordinates) assert len(fc['features']) == len(block_windows) assert check_features_block_windows(fc['features'], src, bidx=1) def test_windows_sequence(runner, path_rgb_byte_tif): result = runner.invoke(main_group, [ 'blocks', path_rgb_byte_tif, '--sequence']) assert result.exit_code == 0 features = tuple(map(json.loads, result.output.splitlines())) with rasterio.open(path_rgb_byte_tif) as src: # Check the coordinates of the first output feature actual_first = features[0] expected_first = next(src.block_windows()) bounds = src.window_bounds(expected_first[1]) xmin, ymin, xmax, ymax = transform_bounds(src.crs, 'EPSG:4326', *bounds) coordinates = [[xmin, ymin], [xmin, ymax], [xmax, ymax], [xmax, ymin]] assert np.array_equal( actual_first['geometry']['coordinates'][0], coordinates) assert check_features_block_windows(features, src, bidx=1) def test_windows_precision(runner, path_rgb_byte_tif): result = runner.invoke(main_group, [ 'blocks', path_rgb_byte_tif, '--precision', 1]) assert result.exit_code == 0 assert result.output.count('"FeatureCollection"') == 1 assert result.output.count('"Feature"') == 240 assert re.search(r'\d*\.\d{2,}', result.output) is None def test_windows_indent(runner, path_rgb_byte_tif): result = runner.invoke(main_group, [ 'blocks', path_rgb_byte_tif, '--indent', 4]) assert result.exit_code == 0 lines = result.output.splitlines() assert result.output.count('"FeatureCollection') == 1 assert result.output.count('"Feature"') == 240 assert len(lines) == 8651 for l in lines: if l.strip() not in ('{', '}'): assert l.startswith(' ') def test_windows_compact(runner, path_rgb_byte_tif): result = runner.invoke(main_group, [ 'blocks', path_rgb_byte_tif, '--compact']) assert result.exit_code == 0 assert result.output.count('"FeatureCollection') == 1 assert result.output.count('"Feature"') == 240 assert result.output.count('", "') == 0 assert result.output.count(': ') == 0 def test_windows_exception(runner, path_rgb_byte_tif): """Tests the try/except that wraps the command logic. The input file does not have 4 bands. """ result = runner.invoke(main_group, [ 'blocks', path_rgb_byte_tif, '--bidx', 4]) assert result.exit_code == 2 assert "Not a valid band index" in result.output def test_windows_projected(runner, path_rgb_byte_tif): result = runner.invoke(main_group, [ 'blocks', path_rgb_byte_tif, '--projected']) assert result.exit_code == 0 fc = json.loads(result.output) with rasterio.open(path_rgb_byte_tif) as src: assert np.array_equal(fc['bbox'], src.bounds) assert check_features_block_windows(fc['features'], src, bidx=1)