Skip to content

Commit

Permalink
updated requirements.in and ensemble tide modelling for exposure (#38)
Browse files Browse the repository at this point in the history
* updated requirements.in and ensemble tide modelling for exposure

* Rearranged exposure.py to move active function to top of the script
  • Loading branch information
erialC-P authored Dec 15, 2023
1 parent a0b0395 commit a0c60db
Show file tree
Hide file tree
Showing 5 changed files with 2,762 additions and 199 deletions.
240 changes: 127 additions & 113 deletions intertidal/elevation.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
round_date_strings,
export_intertidal_rasters,
)
from intertidal.tide_modelling import pixel_tides_ensemble
from intertidal.extents import extents
from intertidal.exposure import exposure
from intertidal.tidal_bias_offset import bias_offset, tidal_offset_tidelines
Expand Down Expand Up @@ -487,119 +488,132 @@ def load_topobathy(
return topobathy_ds


def pixel_tides_ensemble(
satellite_ds,
directory,
ancillary_points,
top_n=3,
models=None,
interp_method="nearest",
):
"""
Generate an ensemble tide model, choosing the best three tide models
for any coastal location using ancillary point data (e.g. altimetry
observations or NDWI correlations along the coastline).
This function generates an ensemble of tidal height predictions for
each pixel in a satellite dataset. Firstly, tides from multiple tide
models are modelled into a low resolution grid using `pixel_tides`.
Ancillary point data is then loaded and interpolated to the same
grid to serve as weightings. These weightings are used to retain
only the top three tidal models, and remaining top models are
combined into a single ensemble output for each time/x/y.
The resulting ensemble tides are then resampled and reprojected to
match the high-resolution satellite data.
Parameters:
-----------
satellite_ds : xarray.Dataset
Three-dimensional dataset containing satellite-derived
information (x by y by time).
directory : str
Directory containing tidal model data; see `pixel_tides`.
ancillary_points : str
Path to a file containing point correlations for different tidal
models.
top_n : integer, optional
The number of top models to use in the ensemble calculation.
Default is 3, which will calculate a median of the top 3 models.
models : list or None, optional
An optional list of tide models to use for the ensemble model.
Default is None, which will use "FES2014", "FES2012", "EOT20",
"TPXO8-atlas-v1", "TPXO9-atlas-v5", "HAMTIDE11", "GOT4.10".
interp_method : str, optional
Interpolation method used to interpolate correlations onto the
low-resolution tide grid. Default is "nearest".
Returns:
--------
tides_highres : xarray.Dataset
High-resolution ensemble tidal heights dataset.
weights_ds : xarray.Dataset
Dataset containing weights for each tidal model used in the ensemble.
"""
# Use default models if none provided
if models is None:
models = [
"FES2014",
"FES2012",
"TPXO8-atlas-v1",
"TPXO9-atlas-v5",
"EOT20",
"HAMTIDE11",
"GOT4.10",
]

# Model tides into every pixel in the three-dimensional
# (x by y by time) satellite dataset
tide_lowres = pixel_tides(
satellite_ds,
resample=False,
model=models,
directory=directory,
)

# Load ancillary points from file, reproject to match satellite
# data, and drop empty points
print("Generating ensemble tide model from point inputs")
corr_gdf = (
gpd.read_file(ancillary_points)[models + ["geometry"]]
.to_crs(satellite_ds.odc.crs)
.dropna()
)

# Loop through each model, interpolating correlations into
# low-res tide grid
out_list = []

for model in models:
out = interpolate_2d(
tide_lowres,
x_coords=corr_gdf.geometry.x,
y_coords=corr_gdf.geometry.y,
z_coords=corr_gdf[model],
method=interp_method,
).expand_dims({"tide_model": [model]})

out_list.append(out)

# Combine along tide model dimension into a single xarray.Dataset
weights_ds = xr.concat(out_list, dim="tide_model")

# Mask out all but the top N models, then take median of remaining
# to produce a single ensemble output for each time/x/y
tide_lowres_ensemble = tide_lowres.where(
(weights_ds.rank(dim="tide_model") > (len(models) - top_n))
).median("tide_model")

# Resample/reproject ensemble tides to match high-res satellite data
tides_highres, tides_lowres = _pixel_tides_resample(
tides_lowres=tide_lowres_ensemble,
ds=satellite_ds,
)

return tides_highres, weights_ds

# def pixel_tides_ensemble(
# satellite_ds,
# directory,
# ancillary_points,
# times=None,
# top_n=3,
# models=None,
# interp_method="nearest",
# ):
# """
# Generate an ensemble tide model, choosing the best three tide models
# for any coastal location using ancillary point data (e.g. altimetry
# observations or NDWI correlations along the coastline).

# This function generates an ensemble of tidal height predictions for
# each pixel in a satellite dataset. Firstly, tides from multiple tide
# models are modelled into a low resolution grid using `pixel_tides`.
# Ancillary point data is then loaded and interpolated to the same
# grid to serve as weightings. These weightings are used to retain
# only the top three tidal models, and remaining top models are
# combined into a single ensemble output for each time/x/y.
# The resulting ensemble tides are then resampled and reprojected to
# match the high-resolution satellite data.

# Parameters:
# -----------
# satellite_ds : xarray.Dataset
# Three-dimensional dataset containing satellite-derived
# information (x by y by time).
# directory : str
# Directory containing tidal model data; see `pixel_tides`.
# ancillary_points : str
# Path to a file containing point correlations for different tidal
# models.
# times : tuple or None, optional
# Tuple containing start and end time of time range to be used for
# tide model in the format of "YYYY-MM-DD".
# top_n : integer, optional
# The number of top models to use in the ensemble calculation.
# Default is 3, which will calculate a median of the top 3 models.
# models : list or None, optional
# An optional list of tide models to use for the ensemble model.
# Default is None, which will use "FES2014", "FES2012", "EOT20",
# "TPXO8-atlas-v1", "TPXO9-atlas-v5", "HAMTIDE11", "GOT4.10".
# interp_method : str, optional
# Interpolation method used to interpolate correlations onto the
# low-resolution tide grid. Default is "nearest".

# Returns:
# --------
# tides_highres : xarray.Dataset
# High-resolution ensemble tidal heights dataset.
# weights_ds : xarray.Dataset
# Dataset containing weights for each tidal model used in the ensemble.
# """
# # Use default models if none provided
# if models is None:
# models = [
# "FES2014",
# "FES2012",
# "TPXO8-atlas-v1",
# "TPXO9-atlas-v5",
# "EOT20",
# "HAMTIDE11",
# "GOT4.10",
# ]

# # Model tides into every pixel in the three-dimensional
# # (x by y by time) satellite dataset

# if times is None:
# tide_lowres = pixel_tides(
# satellite_ds,
# resample=False,
# model=models,
# directory=directory,
# )
# else:
# tide_lowres = pixel_tides(
# satellite_ds,
# resample=False,
# times=times,
# model=models,
# directory=directory,
# )

# # Load ancillary points from file, reproject to match satellite
# # data, and drop empty points
# print("Generating ensemble tide model from point inputs")
# corr_gdf = (
# gpd.read_file(ancillary_points)[models + ["geometry"]]
# .to_crs(satellite_ds.odc.crs)
# .dropna()
# )

# # Loop through each model, interpolating correlations into
# # low-res tide grid
# out_list = []

# for model in models:
# out = interpolate_2d(
# tide_lowres,
# x_coords=corr_gdf.geometry.x,
# y_coords=corr_gdf.geometry.y,
# z_coords=corr_gdf[model],
# method=interp_method,
# ).expand_dims({"tide_model": [model]})

# out_list.append(out)

# # Combine along tide model dimension into a single xarray.Dataset
# weights_ds = xr.concat(out_list, dim="tide_model")

# # Mask out all but the top N models, then take median of remaining
# # to produce a single ensemble output for each time/x/y
# tide_lowres_ensemble = tide_lowres.where(
# (weights_ds.rank(dim="tide_model") > (len(models) - top_n))
# ).median("tide_model")

# # Resample/reproject ensemble tides to match high-res satellite data
# tides_highres, tides_lowres = _pixel_tides_resample(
# tides_lowres=tide_lowres_ensemble,
# ds=satellite_ds,
# )

# return tides_highres, weights_ds

def ds_to_flat(
satellite_ds,
Expand Down
Loading

0 comments on commit a0c60db

Please sign in to comment.