-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathreader.py
97 lines (74 loc) · 2.98 KB
/
reader.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"""Custom STAC reader."""
from typing import Any, Dict, Optional, Set, Type
import attr
import pystac
import rasterio
from morecantile import TileMatrixSet
from rasterio.crs import CRS
from rio_tiler.constants import WEB_MERCATOR_TMS, WGS84_CRS
from rio_tiler.errors import InvalidAssetName, MissingAssets
from rio_tiler.io import BaseReader, MultiBaseReader, Reader
from rio_tiler.io.stac import DEFAULT_VALID_TYPE, _get_assets
from rio_tiler.types import AssetInfo
@attr.s
class PgSTACReader(MultiBaseReader):
"""Custom STAC Reader.
Only accept `pystac.Item` as input (while rio_tiler.io.STACReader accepts url or pystac.Item)
"""
input: pystac.Item = attr.ib()
tms: TileMatrixSet = attr.ib(default=WEB_MERCATOR_TMS)
minzoom: int = attr.ib()
maxzoom: int = attr.ib()
geographic_crs: CRS = attr.ib(default=WGS84_CRS)
include_assets: Optional[Set[str]] = attr.ib(default=None)
exclude_assets: Optional[Set[str]] = attr.ib(default=None)
include_asset_types: Set[str] = attr.ib(default=DEFAULT_VALID_TYPE)
exclude_asset_types: Optional[Set[str]] = attr.ib(default=None)
reader: Type[BaseReader] = attr.ib(default=Reader)
reader_options: Dict = attr.ib(factory=dict)
ctx: Any = attr.ib(default=rasterio.Env)
def __attrs_post_init__(self):
"""Fetch STAC Item and get list of valid assets."""
self.bounds = self.input.bbox
self.crs = WGS84_CRS
self.assets = list(
_get_assets(
self.input,
include=self.include_assets,
exclude=self.exclude_assets,
include_asset_types=self.include_asset_types,
exclude_asset_types=self.exclude_asset_types,
)
)
if not self.assets:
raise MissingAssets("No valid asset found")
@minzoom.default
def _minzoom(self):
return self.tms.minzoom
@maxzoom.default
def _maxzoom(self):
return self.tms.maxzoom
def _get_asset_info(self, asset: str) -> AssetInfo:
"""Validate asset names and return asset's info."""
if asset not in self.assets:
raise InvalidAssetName(
f"{asset} is not valid. Should be one of {self.assets}"
)
asset_info = self.input.assets[asset]
extras = asset_info.extra_fields
info = AssetInfo(
url=asset_info.get_absolute_href() or asset_info.href,
metadata=extras,
)
if "file:header_size" in asset_info.extra_fields:
h = asset_info.extra_fields["file:header_size"]
info["env"] = {"GDAL_INGESTED_BYTES_AT_OPEN": h}
if bands := extras.get("raster:bands"):
stats = [
(b["statistics"]["minimum"], b["statistics"]["maximum"])
for b in bands
if {"minimum", "maximum"}.issubset(b.get("statistics", {}))
]
if len(stats) == len(bands):
info["dataset_statistics"] = stats
return info