-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path__init__.py
More file actions
288 lines (250 loc) · 8.13 KB
/
Copy path__init__.py
File metadata and controls
288 lines (250 loc) · 8.13 KB
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
"""abovepy — KyFromAbove LiDAR, DEM, and orthoimagery data access for Python.
All data is publicly available. No credentials required.
Quick start:
import abovepy
# Find DEM tiles covering Frankfort
tiles = abovepy.search(bbox=(-84.9, 38.15, -84.8, 38.25), product="dem_phase3")
# Or search by county name
tiles = abovepy.search(county="Franklin", product="dem_phase3")
# Download
paths = abovepy.download(tiles, output_dir="./data")
# Mosaic into a single VRT
vrt = abovepy.mosaic(paths, output="frankfort.vrt")
# Stream a window without downloading
data, profile = abovepy.read(tiles.iloc[0].asset_url, bbox=(-84.85, 38.18, -84.82, 38.21))
"""
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING, Any
from abovepy._exceptions import (
AbovepyError,
BboxError,
CountyError,
DownloadError,
MosaicError,
PackageError,
ProductError,
ReadError,
SearchError,
)
from abovepy._version import __version__
from abovepy.client import KyFromAboveClient
from abovepy.mosaics import county_mosaic_url
from abovepy.obliques import list_oblique_seasons, search_obliques
from abovepy.package import Package
from abovepy.products import Product, ProductType, list_products
from abovepy.result import SearchResult
from abovepy.stac import clear_cache
from abovepy.titiler import register_search
from abovepy.utils.bbox import list_counties
from abovepy.utils.crs import buffer_feet, corridor_buffer
from abovepy.validate import ValidationResult, validate
from abovepy.viz import preview_url, show, tile_url
if TYPE_CHECKING:
import geopandas as gpd
import pandas as pd
from shapely.geometry.base import BaseGeometry
_default_client: KyFromAboveClient | None = None
def _get_client() -> KyFromAboveClient:
"""Get or create the default client instance."""
global _default_client
if _default_client is None:
_default_client = KyFromAboveClient()
return _default_client
def search(
bbox: tuple[float, float, float, float] | None = None,
product: str = "dem_phase3",
county: str | None = None,
crs: str = "EPSG:4326",
datetime: str | None = None,
max_items: int = 500,
intersects: dict[str, Any] | BaseGeometry | None = None,
filter: dict[str, Any] | str | None = None,
sortby: list[str] | str | None = None,
ids: list[str] | None = None,
fields: list[str] | None = None,
point: tuple[float, float] | None = None,
buffer_miles: float | None = None,
buffer_feet: float | None = None,
geometry: BaseGeometry | None = None,
) -> SearchResult:
"""Find KyFromAbove tiles intersecting an area of interest.
Provide one of: ``bbox``, ``county``, ``point``, ``geometry``,
``intersects``, or ``ids``.
Parameters
----------
bbox : tuple, optional
Bounding box as (xmin, ymin, xmax, ymax).
product : str
Product key (e.g., ``"dem_phase3"``, ``"ortho_phase3"``).
county : str, optional
Kentucky county name (e.g., "Pike", "Franklin"). Case-insensitive.
crs : str
CRS of the input bbox. Default "EPSG:4326". Ignored if county is used.
datetime : str, optional
ISO 8601 datetime range (e.g., "2022-01/2024-01").
max_items : int
Maximum tiles to return. Default 500.
intersects : dict or Shapely geometry, optional
GeoJSON geometry or Shapely geometry for spatial intersection.
filter : dict or str, optional
CQL2 filter expression for advanced STAC queries.
sortby : list[str] or str, optional
Sort fields (e.g., ``["+datetime"]``).
ids : list[str], optional
Specific STAC item IDs to fetch.
fields : list[str], optional
Fields to include/exclude from the STAC response.
point : tuple, optional
(longitude, latitude) point. Used with ``buffer_miles`` or
``buffer_feet``.
buffer_miles : float, optional
Buffer radius in miles around ``point`` or ``geometry``.
buffer_feet : float, optional
Buffer radius in US survey feet around ``point`` or ``geometry``.
Uses EPSG:3089 projection for accurate measurement. Takes
precedence over ``buffer_miles`` if both are provided.
geometry : Shapely geometry, optional
Any Shapely geometry for spatial search.
Returns
-------
SearchResult
Tile index wrapped in a workflow object. Access the raw
GeoDataFrame via ``.tiles`` or ``.to_geodataframe()``.
"""
return _get_client().search(
bbox=bbox,
product=product,
county=county,
crs=crs,
datetime=datetime,
max_items=max_items,
intersects=intersects,
filter=filter,
sortby=sortby,
ids=ids,
fields=fields,
point=point,
buffer_miles=buffer_miles,
buffer_feet=buffer_feet,
geometry=geometry,
)
def download(
tiles: gpd.GeoDataFrame | SearchResult,
output_dir: str | Path,
overwrite: bool = False,
) -> list[Path]:
"""Download tiles to a local directory.
Parameters
----------
tiles : GeoDataFrame or SearchResult
Tile index from search().
output_dir : str or Path
Directory to save downloaded files.
overwrite : bool
Overwrite existing files. Default False.
Returns
-------
list[Path]
Paths to downloaded files.
"""
if isinstance(tiles, SearchResult):
tiles = tiles.tiles
return _get_client().download(tiles=tiles, output_dir=output_dir, overwrite=overwrite)
def read(
source: str | Path,
bbox: tuple[float, float, float, float] | None = None,
crs: str | None = None,
) -> tuple[Any, dict[str, Any]]:
"""Read a tile or remote source, optionally windowed to a bbox.
Parameters
----------
source : str or Path
Local path, S3 URI, or HTTPS URL to a raster tile.
bbox : tuple, optional
Bounding box for windowed read (xmin, ymin, xmax, ymax).
crs : str, optional
CRS of the bbox. Default matches source CRS.
Returns
-------
tuple[numpy.ndarray, dict]
(data, profile) — raster array and rasterio profile.
"""
return _get_client().read(source=source, bbox=bbox, crs=crs)
def mosaic(
tiles_or_paths: Any,
bbox: tuple[float, float, float, float] | None = None,
output: str | Path | None = None,
crs: str | None = None,
) -> Any:
"""Mosaic tiles into a single raster or VRT.
Defaults to VRT (zero-copy) unless output has a .tif extension.
Parameters
----------
tiles_or_paths : list[Path], GeoDataFrame, or SearchResult
Tile file paths, tile index, or search result.
bbox : tuple, optional
Clip output to this bounding box.
output : str or Path, optional
Output path. .vrt → VRT, .tif → GeoTIFF. None → in-memory.
crs : str, optional
Reproject output to this CRS.
Returns
-------
Path or tuple[numpy.ndarray, dict]
"""
if isinstance(tiles_or_paths, SearchResult):
tiles_or_paths = tiles_or_paths.tiles
return _get_client().mosaic(
tiles_or_paths=tiles_or_paths,
bbox=bbox,
output=output,
crs=crs,
)
def info(source: str | None = None) -> pd.DataFrame | dict[str, Any]:
"""Inspect products or a specific remote tile.
Parameters
----------
source : str, optional
Product key, URL, or S3 URI. None returns all products.
Returns
-------
pandas.DataFrame or dict
"""
return _get_client().info(source=source)
__all__ = [
"AbovepyError",
"BboxError",
"CountyError",
"DownloadError",
"KyFromAboveClient",
"MosaicError",
"Package",
"PackageError",
"Product",
"ProductError",
"ProductType",
"ReadError",
"SearchError",
"SearchResult",
"ValidationResult",
"__version__",
"buffer_feet",
"clear_cache",
"corridor_buffer",
"county_mosaic_url",
"download",
"info",
"list_counties",
"list_oblique_seasons",
"list_products",
"mosaic",
"preview_url",
"read",
"register_search",
"search",
"search_obliques",
"show",
"tile_url",
"validate",
]