Source code for streamstats.watershed

# -*- coding: utf-8 -*-
"""Functionality for finding watershed information for specific locations."""

from collections import OrderedDict
from streamstats import utils


[docs]class Watershed(): """Watershed covering a spatial region, with associated information. The USGS StreamStats API is built around watersheds as organizational units. Watersheds in the 50 U.S. states can be found using lat/lon lookups, along with information about the watershed including its HUC code and a GeoJSON representation of the polygon of a watershed. Basin characteristics can also be extracted from watersheds. """ base_url = "https://streamstats.usgs.gov/streamstatsservices/" def __init__(self, lat, lon): """Initialize a Watershed object :param lon: Longitude of point in decimal degrees. :type lon: float :param lat: Latitude of point in decimal degrees. :type lat: float :param simplify: Whether to simplify the polygon representation. :type simplify: bool """ self.lat, self.lon = lat, lon self.state = utils.find_state(utils.find_address(lat=lat, lon=lon)) self.data = self._delineate() self.workspace = self.data['workspaceID'] self.parameters = self.data['parameters'] def __repr__(self): """Get the string representation of a watershed.""" huc = self.huc huc_message = 'Watershed object with HUC%s: %s' % (len(huc), huc) coord_message = 'containing lat/lon: (%s, %s)' % (self.lat, self.lon) return ', '.join((huc_message, coord_message)) def _delineate(self): """Find the watershed that contains a point. Implements a Delineate Watershed by Location query from https://streamstats.usgs.gov/docs/streamstatsservices/#/ :rtype dict containing watershed data """ payload = { 'rcode': self.state, 'xlocation': self.lon, 'ylocation': self.lat, 'crs': 4326, 'includeparameters': True, 'includeflowtypes': False, 'includefeatures': True, 'simplify': False } url = "".join((self.base_url, "watershed.geojson")) response = utils.requests_retry_session().get(url, params=payload) response.raise_for_status() # raises errors early return response.json() @property def huc(self): """Find the Hydrologic Unit Code (HUC) of the watershed.""" watershed_point = self.data['featurecollection'][0]['feature'] huc = watershed_point['features'][0]['properties']['HUCID'] return huc @property def boundary(self): """Return the full watershed GeoJSON as a dictionary. :rtype dict containing GeoJSON watershed boundary """ for dictionary in self.data['featurecollection']: if dictionary.get('name', '') == 'globalwatershed': return dictionary['feature'] raise LookupError('Could not find "globalwatershed" in the feature' 'collection.') @property def characteristics(self): """List the available watershed characteristics. Details about these characteristics can be found in the StreamStats docs: https://streamstatsags.cr.usgs.gov/ss_defs/basin_char_defs.aspx :rtype OrderedDict with characteristic codes and descriptions """ chars = OrderedDict((p['code'], p['name']) for p in self.parameters) return chars
[docs] def get_characteristic(self, code=None): """Retrieve a specified watershed characteristic :param code: Watershed characteristic code to extract. :type code: string get_characteristic() requires a characteristic code as an argument. Valid codes can be seen as keys in the dictionary returned by the characteristics() method. :rtype dict containing specified characteristic's data and metadata """ keys = list(self.characteristics.keys()) if code not in keys: raise ValueError("code must be a valid key: %s" % ', '.join(keys)) characteristic_index = keys.index(code) characteristic_values = self.parameters[characteristic_index] return characteristic_values