Source code for watershed_workflow.sources.manager_3dep
"""Manager for downloading 3DEP data."""
from typing import Tuple, Optional, List
import cftime
import logging
import shapely.geometry
import xarray as xr
import py3dep
import watershed_workflow.crs
from watershed_workflow.crs import CRS
from . import manager_dataset
[docs]
class Manager3DEP(manager_dataset.ManagerDataset):
"""3D Elevation Program (3DEP) data manager.
Provides access to USGS 3DEP elevation and derived products through
the py3dep library. Supports multiple resolution options and various
topographic layers including DEM, slope, aspect, and hillshade products.
"""
def __init__(self, resolution : int):
"""Downloads DEM data from the 3DEP.
Parameters
----------
resolution : int
Resolution in meters. Valid resolutions are: 60, 30, or 10.
"""
self._resolution = resolution
resolution_in_degrees = 2 * resolution * 9e-6
in_crs = CRS.from_epsg(4326) # lat-long
out_crs = CRS.from_epsg(5070) # CONUS Albers Equal Area
valid_variables = [
'DEM', 'Hillshade Gray', 'Aspect Degrees', 'Aspect Map',
'GreyHillshade_elevationFill', 'Hillshade Multidirectional',
'Slope Map', 'Slope Degrees', 'Hillshade Elevation Tinted',
'Height Ellipsoidal', 'Contour 25', 'Contour Smoothed 25'
]
default_variables = ['DEM']
# Initialize base class with native properties
super().__init__('3DEP', 'py3dep', resolution_in_degrees, in_crs, out_crs,
None, None, valid_variables, default_variables)
def _requestDataset(self, request : manager_dataset.ManagerDataset.Request
) -> manager_dataset.ManagerDataset.Request:
"""Request the data -- ready upon request."""
request.is_ready = True
return request
def _fetchDataset(self, request : manager_dataset.ManagerDataset.Request) -> xr.Dataset:
"""Implementation of abstract method to get 3DEP data."""
# Base class ensures these for multi-variable, time independent class
assert request.variables is not None
assert request.start is None
assert request.end is None
# Use instance resolution and native CRS
logging.info(f'Getting DEM with map of area = {request.geometry.area}')
result = py3dep.get_map(request.variables, request.geometry, self._resolution,
geo_crs=self.native_crs_in, crs=self.native_crs_out)
# py3dep returns DataArray for single layer, Dataset for multiple layers
if isinstance(result, xr.DataArray):
# Convert DataArray to Dataset
result = result.to_dataset(name=request.variables[0].lower().replace(' ', '_'))
return result