def ssebopeta_bygeom( geometry: Union[Polygon, Tuple[float, float, float, float]], dates: Union[Tuple[str, str], Union[int, List[int]]], geo_crs: str = DEF_CRS, fill_holes: bool = False, ) -> xr.DataArray: """Get daily actual ET for a region from SSEBop database. Notes ----- Since there's still no web service available for subsetting SSEBop, the data first needs to be downloaded for the requested period then it is masked by the region of interest locally. Therefore, it's not as fast as other functions and the bottleneck could be the download speed. Parameters ---------- geometry : shapely.geometry.Polygon or tuple The geometry for downloading clipping the data. For a tuple bbox, the order should be (west, south, east, north). dates : tuple or list, optional Start and end dates as a tuple (start, end) or a list of years [2001, 2010, ...]. geo_crs : str, optional The CRS of the input geometry, defaults to epsg:4326. fill_holes : bool, optional Whether to fill the holes in the geometry's interior (Polygon type), defaults to False. Returns ------- xarray.DataArray Daily actual ET within a geometry in mm/day at 1 km resolution """ _geometry = geoutils.geo2polygon(geometry, geo_crs, DEF_CRS) _geometry = Polygon(_geometry.exterior) if fill_holes else _geometry f_list = _get_ssebopeta_urls(dates) session = RetrySession() with session.onlyipv4(): def _ssebop(url_stamped): dt, url = url_stamped resp = session.get(url) zfile = zipfile.ZipFile(io.BytesIO(resp.content)) content = zfile.read(zfile.filelist[0].filename) ds = geoutils.gtiff2xarray({"eta": content}, _geometry, DEF_CRS) return dt, ds.expand_dims({"time": [dt]}) resp_list = ogc.utils.threading(_ssebop, f_list, max_workers=4) data = xr.merge( OrderedDict(sorted(resp_list, key=lambda x: x[0])).values()) eta = data.eta.copy() eta *= 1e-3 eta.attrs.update({"units": "mm/day", "nodatavals": (np.nan, )}) return eta
def test_ipv4(): url = ( "https://edcintl.cr.usgs.gov/downloads/sciweb1/shared/uswem/web/conus" + "/eta/modis_eta/daily/downloads/det2004003.modisSSEBopETactual.zip") session = RetrySession() with session.onlyipv4(): r = session.get(url) z = zipfile.ZipFile(io.BytesIO(r.content)) fname = z.read(z.filelist[0].filename) assert sys.getsizeof(fname) == 4361682
def ssebopeta_byloc( coords: Tuple[float, float], dates: Union[Tuple[str, str], Union[int, List[int]]], ) -> pd.DataFrame: """Daily actual ET for a location from SSEBop database in mm/day. Parameters ---------- coords : tuple Longitude and latitude of the location of interest as a tuple (lon, lat) dates : tuple or list, optional Start and end dates as a tuple (start, end) or a list of years [2001, 2010, ...]. Returns ------- pandas.DataFrame Daily actual ET for a location """ if isinstance(coords, tuple) and len(coords) == 2: lon, lat = coords else: raise InvalidInputType("coords", "tuple", "(lon, lat)") f_list = _get_ssebopeta_urls(dates) session = RetrySession() with session.onlyipv4(): def _ssebop(urls): dt, url = urls r = session.get(url) z = zipfile.ZipFile(io.BytesIO(r.content)) with rio.MemoryFile() as memfile: memfile.write(z.read(z.filelist[0].filename)) with memfile.open() as src: return { "dt": dt, "eta": [e[0] for e in src.sample([(lon, lat)])][0], } eta_list = ogc.utils.threading(_ssebop, f_list, max_workers=4) eta = pd.DataFrame.from_records(eta_list) eta.columns = ["datetime", "eta (mm/day)"] eta = eta.set_index("datetime") return eta * 1e-3