Skip to content

Commit 073aad2

Browse files
author
Jon Duckworth
authored
Merge pull request #548 from gadomski/feature/projection-crs-string
Add `ProjectionExtension.crs_string`
2 parents 12eff70 + 17d94fb commit 073aad2

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
### Added
66

7+
- `ProjectionExtension.crs_string` to provide a single string to describe the coordinate reference system (CRS).
8+
Useful because projections can be defined by EPSG code, WKT, or projjson.
9+
([#548](https://github.com/stac-utils/pystac/pull/548))
10+
711
### Removed
812

913
### Changed

pystac/extensions/projection.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
https://github.com/stac-extensions/projection
44
"""
55

6+
import json
67
from typing import Any, Dict, Generic, Iterable, List, Optional, TypeVar, cast
78

89
import pystac
@@ -144,6 +145,27 @@ def projjson(self) -> Optional[Dict[str, Any]]:
144145
def projjson(self, v: Optional[Dict[str, Any]]) -> None:
145146
self._set_property(PROJJSON_PROP, v)
146147

148+
@property
149+
def crs_string(self) -> Optional[str]:
150+
"""Returns the coordinate reference system (CRS) string for the extension.
151+
152+
This string can be used to feed, e.g., ``rasterio.crs.CRS.from_string``.
153+
The string is determined by the following heuristic:
154+
155+
1. If an EPSG code is set, return "EPSG:{code}", else
156+
2. If wkt2 is set, return the WKT string, else,
157+
3. If projjson is set, return the projjson as a string, else,
158+
4. Return None
159+
"""
160+
if self.epsg:
161+
return f"EPSG:{self.epsg}"
162+
elif self.wkt2:
163+
return self.wkt2
164+
elif self.projjson:
165+
return json.dumps(self.projjson)
166+
else:
167+
return None
168+
147169
@property
148170
def geometry(self) -> Optional[Dict[str, Any]]:
149171
"""Get or sets a Polygon GeoJSON dict representing the footprint of this item.

tests/extensions/test_projection.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,28 @@ def test_projjson(self) -> None:
222222
ProjectionExtension.ext(proj_item).projjson = {"bad": "data"}
223223
proj_item.validate()
224224

225+
def test_crs_string(self) -> None:
226+
item = pystac.Item.from_file(self.example_uri)
227+
ProjectionExtension.remove_from(item)
228+
for key in list(item.properties.keys()):
229+
if key.startswith("proj:"):
230+
item.properties.pop(key)
231+
self.assertIsNone(item.properties.get("proj:epsg"))
232+
self.assertIsNone(item.properties.get("proj:wkt2"))
233+
self.assertIsNone(item.properties.get("proj:projjson"))
234+
235+
projection = ProjectionExtension.ext(item, add_if_missing=True)
236+
self.assertIsNone(projection.crs_string)
237+
238+
projection.projjson = PROJJSON
239+
self.assertEqual(projection.crs_string, json.dumps(PROJJSON))
240+
241+
projection.wkt2 = WKT2
242+
self.assertEqual(projection.crs_string, WKT2)
243+
244+
projection.epsg = 4326
245+
self.assertEqual(projection.crs_string, "EPSG:4326")
246+
225247
def test_geometry(self) -> None:
226248
proj_item = pystac.Item.from_file(self.example_uri)
227249

0 commit comments

Comments
 (0)