Source code for dea_tools.waterbodies
## dea_waterbodies.py
"""
Loading and processing DEA Waterbodies data.
License: The code in this notebook is licensed under the Apache License,
Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0). Digital Earth
Australia data is licensed under the Creative Commons by Attribution 4.0
license (https://creativecommons.org/licenses/by/4.0/).
Contact: If you need assistance, please post a question on the Open Data
Cube Discord chat (https://discord.com/invite/4hhBQVas5U) or on the GIS Stack
Exchange (https://gis.stackexchange.com/questions/ask?tags=open-data-cube)
using the `open-data-cube` tag (you can view previously asked questions
here: https://gis.stackexchange.com/questions/tagged/open-data-cube).
If you would like to report an issue with this script, file one on
GitHub: https://github.com/GeoscienceAustralia/dea-notebooks/issues/new
Last modified: March 2024
"""
import geopandas as gpd
from owslib.wfs import WebFeatureService
from owslib.fes import PropertyIsEqualTo
from owslib.etree import etree
import pandas as pd
WFS_ADDRESS = "https://geoserver.dea.ga.gov.au/geoserver/wfs"
LAYER_SELECT = {
"v2" : "DigitalEarthAustraliaWaterbodies_v2",
"v3" : "DigitalEarthAustraliaWaterbodies_v3"
}
[docs]
def get_waterbody(geohash: str, version: str = "v3") -> gpd.GeoDataFrame:
"""Gets a waterbody polygon and metadata by geohash.
Parameters
----------
geohash : str
The geohash/UID for a waterbody in DEA Waterbodies.
Returns
-------
gpd.GeoDataFrame
A GeoDataFrame with the polygon.
"""
wfs = WebFeatureService(url=WFS_ADDRESS, version="1.1.0")
filter_ = PropertyIsEqualTo(propertyname="uid", literal=geohash)
filterxml = etree.tostring(filter_.toXML()).decode("utf-8")
response = wfs.getfeature(
typename=LAYER_SELECT[version],
filter=filterxml,
outputFormat="json",
)
wb_gpd = gpd.read_file(response)
return wb_gpd
[docs]
def get_waterbodies(bbox: tuple, crs="EPSG:4326", version: str = "v3") -> gpd.GeoDataFrame:
"""Gets the polygons and metadata for multiple waterbodies by bbox.
Parameters
----------
bbox : (xmin, ymin, xmax, ymax)
Bounding box.
crs : str
Optional CRS for the bounding box.
Returns
-------
gpd.GeoDataFrame
A GeoDataFrame with the polygons and metadata.
"""
wfs = WebFeatureService(url=WFS_ADDRESS, version="1.1.0")
response = wfs.getfeature(
typename=LAYER_SELECT[version],
bbox=tuple(bbox) + (crs,),
outputFormat="json",
)
wb_gpd = gpd.read_file(response)
return wb_gpd
[docs]
def get_geohashes(bbox: tuple = None, crs: str = "EPSG:4326", version: str = "v3") -> [str]:
"""Gets all waterbody geohashes.
Parameters
----------
bbox : (xmin, ymin, xmax, ymax)
Optional bounding box.
crs : str
Optional CRS for the bounding box.
Returns
-------
[str]
A list of geohashes.
"""
wfs = WebFeatureService(url=WFS_ADDRESS, version="1.1.0")
if bbox is not None:
bbox = tuple(bbox) + (crs,)
response = wfs.getfeature(
typename=LAYER_SELECT[version],
propertyname="uid",
outputFormat="json",
bbox=bbox,
)
wb_gpd = gpd.read_file(response)
return list(wb_gpd["uid"])
[docs]
def get_time_series(geohash: str = None, waterbody: pd.Series = None, version: str = "v3") -> pd.DataFrame:
"""Gets the time series for a waterbody. Specify either a GeoDataFrame row or a geohash.
Parameters
----------
geohash : str
The geohash/UID for a waterbody in DEA Waterbodies.
waterbody : pd.Series
One row of a GeoDataFrame representing a waterbody.
Returns
-------
pd.DataFrame
A time series for the waterbody.
"""
if waterbody is not None and geohash is not None:
raise ValueError("One of waterbody and geohash must be None")
if waterbody is None and geohash is None:
raise ValueError("One of waterbody and geohash must be specified")
if geohash is not None:
wb = get_waterbody(geohash, version)
url = wb.timeseries[0]
else:
url = waterbody.timeseries
wb_timeseries = pd.read_csv(url)
# Tidy up the dataframe.
wb_timeseries.dropna(inplace=True)
wb_timeseries.columns = ["date", "pc_wet", "px_wet"]
wb_timeseries = wb_timeseries.set_index("date")
wb_timeseries.index = pd.to_datetime(wb_timeseries.index)
return wb_timeseries