Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rpc_from_geotiff fails if there is a textual RPC.txt next to the tiff #15

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion rpcm/rpc_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)


Expand Down
54 changes: 49 additions & 5 deletions tests/test_rpc_constructors.py
Original file line number Diff line number Diff line change
@@ -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