Skip to content

Commit

Permalink
Merge pull request #44 from kbevers/coordinate_units
Browse files Browse the repository at this point in the history
Include CRS axis units in CRS routes
  • Loading branch information
larsnaesbye authored Jul 15, 2022
2 parents 0722de6 + 4ccd9d2 commit 249d6fa
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 42 deletions.
98 changes: 56 additions & 42 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,24 @@ def _assert_result(entry, expected_json_output):
assert decoded_response == expected_json_output


def _assert_key_value_set(entry, expected_key_value_set):
"""
Check that a returned response contains the expected key
value set
"""
print(entry)
decoded_response = _get_and_decode_response(entry)
pprint.pprint(decoded_response)
print("-----")
pprint.pprint(expected_key_value_set)
for key in expected_key_value_set.keys():
if key not in decoded_response.keys():
raise AssertionError

for key, value in expected_key_value_set.items():
assert decoded_response[key] == value


def _assert_coordinate(entry, expected_json_output, tolerance=1e-6):
"""
Check that a returned coordinate matches the expected result
Expand All @@ -51,16 +69,21 @@ def _assert_coordinate(entry, expected_json_output, tolerance=1e-6):
raise AssertionError


@pytest.fixture(scope="module", params=["v1.0", "v1.1"])
@pytest.fixture(scope="module", params=["v1.0", "v1.1", "v1.2"])
def api_all(request):
return request.param


@pytest.fixture(scope="module", params=["v1.1"])
@pytest.fixture(scope="module", params=["v1.1", "v1.2"])
def api_from_v1_1(request):
return request.param


@pytest.fixture(scope="module", params=["v1.2"])
def api_from_v1_2(request):
return request.param


def test_transformer_caching():
"""
Check that caching works by comparing objects with the is operator
Expand Down Expand Up @@ -306,55 +329,46 @@ def test_crs_return_srid(api_from_v1_1):
"""
testdata = {
"EPSG:25832": {
"country": "DK",
"title": "ETRS89 / UTM Zone 32 Nord",
"title_short": "ETRS89/UTM32N",
"v1": "Easting",
"v1_short": "x",
"v2": "Northing",
"v2_short": "y",
"v3": "Ellipsoidehøjde",
"v3_short": "h",
"v4": None,
"v4_short": None,
"srid": "EPSG:25832",
"area_of_use": "Europe between 6°E and 12°E: Austria; Belgium; Denmark - onshore and offshore; Germany - onshore and offshore; Norway including - onshore and offshore; Spain - offshore.",
"bounding_box": [6.0, 38.76, 12.0, 84.33],
},
"EPSG:23032+5733": {
"country": "DK",
"title": "ED50 / UTM Zone 32 Nord + Dansk Normal Nul",
"title_short": "ED50/UTM32N + DNN",
"v1": "Easting",
"v1_short": "x",
"v2": "Northing",
"v2_short": "y",
"v3": "Ellipsoidehøjde",
"v3_short": "h",
"v4": None,
"v4_short": None,
"srid": "EPSG:23032+5733",
"area_of_use": "Denmark - onshore.",
"bounding_box": [8.0, 54.51, 15.24, 57.8],
},
"DK:S34S": {
"country": "DK",
"title": "System 34 Sjælland",
"title_short": "S34S",
"v1": "Westing",
"v1_short": "x",
"v2": "Northing",
"v2_short": "y",
"v3": None,
"v3_short": None,
"v4": None,
"v4_short": None,
"srid": "DK:S34S",
"area_of_use": "Denmark - Sealand onshore",
"bounding_box": [11.0, 54.5, 12.8, 56.5],
},
}

for srid, crsinfo in testdata.items():
api_entry = f"/{api_from_v1_1}/crs/{srid}"
_assert_result(api_entry, crsinfo)
_assert_key_value_set(api_entry, crsinfo)


def test_crs_units(api_from_v1_2):
"""
Test that CRS routes return the CRS axis units.
"""
testdata = {
"EPSG:25832": {
"v1_unit": "metre",
"v2_unit": "metre",
"v3_unit": None,
"v4_unit": None,
},
"EPSG:23032+5733": {
"v1_unit": "metre",
"v2_unit": "metre",
"v3_unit": "metre",
"v4_unit": None,
},
"DK:S34S": {
"v1_unit": "metre",
"v2_unit": "metre",
"v3_unit": None,
"v4_unit": None,
},
}

for srid, crsinfo in testdata.items():
api_entry = f"/{api_from_v1_2}/crs/{srid}"
_assert_key_value_set(api_entry, crsinfo)
42 changes: 42 additions & 0 deletions webproj/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ def get(self):

@api.route("/v1.0/crs/")
@api.route("/v1.1/crs/")
@api.route("/v1.2/crs/")
class CRSIndex(Resource):
def get(self):
"""
Expand Down Expand Up @@ -246,8 +247,45 @@ def get(self, crs):
return output


@api.route("/v1.2/crs/<string:crs>")
class CRSv1_2(CRSv1_1):
def get(self, crs):
"""
Retrieve information about a given coordinate reference system
Version 1.2 includes coodinate units of the returned CRS.
"""
output = super().get(crs)
# initialize unit elements in output dict
for i in range(1, 5):
output[f"v{i}_unit"] = None

try:
crs_from_db = pyproj.CRS.from_user_input(crs.upper())
for i, axis in enumerate(crs_from_db.axis_info, start=1):
output[f"v{i}_unit"] = axis.unit_name

except pyproj.exceptions.CRSError:
# special cases not in proj.db
if crs == "DK:S34J":
output["v1_unit"] = "metre"
output["v2_unit"] = "metre"
elif crs == "DK:S34S":
output["v1_unit"] = "metre"
output["v2_unit"] = "metre"
elif crs == "DK:S45B":
output["v1_unit"] = "metre"
output["v2_unit"] = "metre"
else:
abort(404, message=f"'{crs}' not available")

# sort output for improved human readability
return dict(sorted(output.items()))


@api.route("/v1.0/trans/<string:src>/<string:dst>/<number:v1>,<number:v2>")
@api.route("/v1.1/trans/<string:src>/<string:dst>/<number:v1>,<number:v2>")
@api.route("/v1.2/trans/<string:src>/<string:dst>/<number:v1>,<number:v2>")
class Transformation2D(Resource):
doc = {
"src": "Source CRS",
Expand All @@ -272,6 +310,7 @@ def get(self, src, dst, v1, v2):

@api.route("/v1.0/trans/<string:src>/<string:dst>/<number:v1>,<number:v2>,<number:v3>")
@api.route("/v1.1/trans/<string:src>/<string:dst>/<number:v1>,<number:v2>,<number:v3>")
@api.route("/v1.2/trans/<string:src>/<string:dst>/<number:v1>,<number:v2>,<number:v3>")
class Transformation3D(Resource):
doc = {
"src": "Source CRS",
Expand Down Expand Up @@ -301,6 +340,9 @@ def get(self, src, dst, v1, v2, v3):
@api.route(
"/v1.1/trans/<string:src>/<string:dst>/<number:v1>,<number:v2>,<number:v3>,<number:v4>"
)
@api.route(
"/v1.2/trans/<string:src>/<string:dst>/<number:v1>,<number:v2>,<number:v3>,<number:v4>"
)
class Transformation4D(Resource):
doc = {
"src": "Source CRS",
Expand Down

0 comments on commit 249d6fa

Please sign in to comment.