Skip to content
Merged
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

### Added

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

### Removed

### Changed
Expand Down
22 changes: 22 additions & 0 deletions pystac/extensions/projection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
https://github.com/stac-extensions/projection
"""

import json
from typing import Any, Dict, Generic, Iterable, List, Optional, TypeVar, cast

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

@property
def crs_string(self) -> Optional[str]:
"""Returns the coordinate reference system (CRS) string for the extension.

This string can be used to feed, e.g., ``rasterio.crs.CRS.from_string``.
The string is determined by the following heuristic:

1. If an EPSG code is set, return "EPSG:{code}", else
2. If wkt2 is set, return the WKT string, else,
3. If projjson is set, return the projjson as a string, else,
4. Return None
"""
if self.epsg:
return f"EPSG:{self.epsg}"
elif self.wkt2:
return self.wkt2
elif self.projjson:
return json.dumps(self.projjson)
else:
return None

@property
def geometry(self) -> Optional[Dict[str, Any]]:
"""Get or sets a Polygon GeoJSON dict representing the footprint of this item.
Expand Down
22 changes: 22 additions & 0 deletions tests/extensions/test_projection.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,28 @@ def test_projjson(self) -> None:
ProjectionExtension.ext(proj_item).projjson = {"bad": "data"}
proj_item.validate()

def test_crs_string(self) -> None:
item = pystac.Item.from_file(self.example_uri)
ProjectionExtension.remove_from(item)
for key in list(item.properties.keys()):
if key.startswith("proj:"):
item.properties.pop(key)
self.assertIsNone(item.properties.get("proj:epsg"))
self.assertIsNone(item.properties.get("proj:wkt2"))
self.assertIsNone(item.properties.get("proj:projjson"))

projection = ProjectionExtension.ext(item, add_if_missing=True)
self.assertIsNone(projection.crs_string)

projection.projjson = PROJJSON
self.assertEqual(projection.crs_string, json.dumps(PROJJSON))

projection.wkt2 = WKT2
self.assertEqual(projection.crs_string, WKT2)

projection.epsg = 4326
self.assertEqual(projection.crs_string, "EPSG:4326")

def test_geometry(self) -> None:
proj_item = pystac.Item.from_file(self.example_uri)

Expand Down