Source code for planetary_coverage.rois.geojson
"""GeoJson ROI module."""
from json import loads
from pathlib import Path as PathFile
from matplotlib.path import Path
from .rois import ROI
[docs]class GeoJsonROI(ROI):
"""GeoJson ROI object.
Parameters
----------
key: str
Identification key.
geojson: str, pathlib.Path
GeoJson file.
**kwargs: str, optional
Region attribute.
Note
----
Only a limited number of `geojson` types are
supported at the moment: ``FeatureCollection``,
``Feature`` and ``Polygon``.
"""
def __init__(self, key, geojson, **kwargs):
super().__init__(key, lons_e=None, lats=None, **kwargs)
# Remove `lons_e` and `lats` attributes
delattr(self, 'lons_e')
delattr(self, 'lats')
del self._attrs['lons_e']
del self._attrs['lats']
self.geojson = geojson
@property
def vertices(self):
"""ROI vertices."""
return self.__vertices
@vertices.setter
def vertices(self, vertices):
"""ROI vertices setter."""
self.__vertices = vertices
@property
def codes(self):
"""ROI path codes."""
return self.__codes
@codes.setter
def codes(self, codes):
"""ROI path codes setter."""
self.__codes = codes
@property
def geojson(self):
"""GeoJson file."""
return self.__geojson
@geojson.setter
def geojson(self, geojson):
"""GeoJson file setter."""
self.__geojson = PathFile(geojson)
json = loads(self.geojson.read_text())
self.load_geojson(json)
[docs] def load_geojson(self, json):
"""Load GeoJson content."""
if json['type'] == 'FeatureCollection':
self._load_feature_collection(json)
elif json['type'] == 'Feature':
self._load_feature(json)
elif json['type'] == 'Polygon':
self._load_geometry(json)
else:
raise NotImplementedError(f'Type: `{json["type"]}`')
def _load_feature_collection(self, json):
"""Load GeoJson feature collection."""
if 'features' not in json:
raise ValueError('The geojson is invalid: `features` key is missing.')
if not json['features']:
raise ValueError('No features found.')
if len(json['features']) > 1:
raise NotImplementedError('No many features. Only 1 is supported.')
self._load_feature(json['features'][0])
def _load_feature(self, json):
"""Load GeoJson feature."""
if 'geometry' not in json:
raise ValueError('The geojson is invalid: `geometry` key is missing.')
self._load_geometry(json['geometry'])
if 'properties' in json:
self._attrs.update(json['properties'])
for key, value in json['properties'].items():
setattr(self, key, value)
def _load_geometry(self, json):
"""Load GeoJson geometry."""
if json['type'] != 'Polygon':
raise NotImplementedError(
f'Invalid type: `{json["type"]}` (only the Polygon is supported)')
if 'coordinates' not in json:
raise ValueError('The geojson is invalid: `coordinates` key is missing.')
self._load_coordinates(json['coordinates'])
def _load_coordinates(self, polygons):
"""Load GeoJson coordinates."""
if not isinstance(polygons, list):
raise ValueError('The geojson is invalid: `coordinates` value is not a list.')
vertices, codes = [], []
for polygon in polygons:
for lon_e, lat in polygon:
vertices.append((lon_e, lat))
npts = len(polygon)
codes += [Path.MOVETO] + (npts - 2) * [Path.LINETO] + [Path.CLOSEPOLY]
self.vertices = vertices
self.codes = codes