diff --git a/rpcm/rpc_model.py b/rpcm/rpc_model.py index 22d9015..07ee3e5 100644 --- a/rpcm/rpc_model.py +++ b/rpcm/rpc_model.py @@ -62,6 +62,22 @@ def apply_rfm(num, den, x, y, z): return apply_poly(num, x, y, z) / apply_poly(den, x, y, z) +def remove_ikonos_units(rpc_dict): + """ + When there is a RPC.txt file along the tif, GDAL will get the rpcs from + the textual file instead of the tif. + However, ikonos textual files contain units along the numbers, and these + are not expected when constructing from GeoTiff. + This function removes the units from the dict. + """ + geotiff_dict = {} + for key, value in rpc_dict.items(): + if key.endswith('_OFF') or key.endswith('_SCALE'): + value = value.split()[0] + geotiff_dict[key] = value + return geotiff_dict + + def rpc_from_geotiff(geotiff_path): """ Read the RPC coefficients from a GeoTIFF file and return an RPCModel object. @@ -73,7 +89,7 @@ def rpc_from_geotiff(geotiff_path): instance of the rpc_model.RPCModel class """ with rasterio.open(geotiff_path, 'r') as src: - rpc_dict = src.tags(ns='RPC') + rpc_dict = remove_ikonos_units(src.tags(ns='RPC')) return RPCModel(rpc_dict) diff --git a/tests/test_rpc_constructors.py b/tests/test_rpc_constructors.py index 8c89af3..7dc439a 100644 --- a/tests/test_rpc_constructors.py +++ b/tests/test_rpc_constructors.py @@ -1,22 +1,66 @@ import os - -from rpcm import RPCModel +import shutil +import numpy as np +import pytest +from rpcm import RPCModel, rpc_from_geotiff +from rpcm.utils import rasterio_write from rpcm.rpc_file_readers import read_rpc_file here = os.path.abspath(os.path.dirname(__file__)) files_dir = os.path.join(here, "test_rpc_files") +def _read_dict_from_file(filename="rpc_IKONOS.txt"): + filepath = os.path.join(files_dir, filename) + return read_rpc_file(filepath) + + def test_rpc_constructors(): """ Test that the two constructors of the RPCModel class yield the same object. """ - filepath = os.path.join(files_dir, "rpc_IKONOS.txt") - - geotiff_dict = read_rpc_file(filepath) + geotiff_dict = _read_dict_from_file("rpc_IKONOS.txt") geotiff_rpc = RPCModel(geotiff_dict, dict_format="geotiff") rpcm_dict = geotiff_rpc.__dict__ rpcm_rpc = RPCModel(rpcm_dict, dict_format="rpcm") assert geotiff_rpc == rpcm_rpc + + +@pytest.fixture +def tmp_geotiff(tmp_path): + """ + provides a geotiff with some rpcs, stored in the tmp_path + """ + data = np.ones([1, 10, 10], dtype=np.uint8) + rpc = RPCModel(_read_dict_from_file()) + tags = dict(ns="RPC", **rpc.to_geotiff_dict()) + + geotiff_path = os.fspath(tmp_path / "test_geo.tif") + rasterio_write(geotiff_path, data, tags=tags) + return geotiff_path + + +def _add_auxiliary_rpc_file(tif_path, rpc_filename="rpc_IKONOS.txt"): + """ + Adds an RPC textfile {basename}_RPC.txt, next to the given `tif_path` + (with filename {basename}.tif). + GDAL recognizes such files, and automatically reads the information from + them as if it was stored inside the tif tags. + """ + src = os.path.join(files_dir, rpc_filename) + dst = tif_path[:-len(".tif")] + "_RPC.txt" + shutil.copyfile(src, dst) + + +def test_from_geotiff(tmp_geotiff, tmp_path): + # Verify that RPCs read from a geotiff match the textual file + txt_rpc = RPCModel(_read_dict_from_file()) + tif_rpc = rpc_from_geotiff(tmp_geotiff) + assert tif_rpc == txt_rpc + + # verify that RPCs from geotiff work if there is an auxiliary file + _add_auxiliary_rpc_file(tmp_geotiff) + tif_rpc = rpc_from_geotiff(tmp_geotiff) + assert tif_rpc == txt_rpc