Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding argument to provide high resolut dem to determine structure height #109

Merged
merged 6 commits into from
Aug 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ New
- Added the option to use landuse/landcover data combined with a reclass table to `SfincsModel.setup_constant_infiltration`. PR #103
- Enabled to provide locations only (so no timeseries) for `SfincsModel.setup_waterlevel_forcing` and `SfincsModel.setup_discharge_forcing` PR #104
- New optional buffer argument in `SfincsModel.setup_discharge_forcing` to select gauges around boundary only. PR #104
- New functionality within `SfincsModel.setup_structures` to use high resolution dem for weir elevation

Changed
-------
Expand Down
42 changes: 37 additions & 5 deletions hydromt_sfincs/sfincs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,8 @@ def setup_structures(
self,
structures: Union[str, Path, gpd.GeoDataFrame],
stype: str,
dep: Union[str, Path, xr.DataArray] = None,
buffer: float = None,
dz: float = None,
merge: bool = True,
**kwargs,
Expand All @@ -1340,6 +1342,12 @@ def setup_structures(
"par1" defaults to 0.6 if gdf has no "par1" column.
stype : {'thd', 'weir'}
Structure type.
dep : str, Path, xr.DataArray, optional
Path, data source name, or xarray raster object ('elevtn') describing the depth in an
alternative resolution which is used for sampling the weir.
buffer : float, optional
If provided, describes the distance from the centerline to the foot of the structure.
This distance is supplied to the raster.sample as the window (wdw).
merge : bool, optional
If True, merge with existing'stype' structures, by default True.
dz: float, optional
Expand All @@ -1356,20 +1364,44 @@ def setup_structures(
"thd": ["name", "geometry"],
"weir": ["name", "z", "par1", "geometry"],
}
assert stype in cols
assert stype in cols, f"stype must be one of {list(cols.keys())}"
gdf = gdf_structures[
[c for c in cols[stype] if c in gdf_structures.columns]
] # keep relevant cols

structs = utils.gdf2linestring(gdf) # check if it parsed correct
# sample zb values from dep file and set z = zb + dz
if stype == "weir" and dz is not None:
elv = self.grid["dep"]
if stype == "weir" and (dep is not None or dz is not None):
if dep is None or dep == "dep":
assert "dep" in self.grid, "dep layer not found"
elv = self.grid["dep"]
else:
elv = self.data_catalog.get_rasterdataset(
dep, geom=self.region, buffer=5, variables=["elevtn"]
)

# calculate window size from buffer
if buffer is not None:
res = abs(elv.raster.res[0])
if elv.raster.crs.is_geographic:
res = res * 111111.0
window_size = int(np.ceil(buffer / res))
else:
window_size = 0
self.logger.debug(f"Sampling elevation with window size {window_size}")

structs_out = []
for s in structs:
pnts = gpd.points_from_xy(x=s["x"], y=s["y"])
zb = elv.raster.sample(gpd.GeoDataFrame(geometry=pnts, crs=self.crs))
s["z"] = zb.values + float(dz)
zb = elv.raster.sample(
gpd.GeoDataFrame(geometry=pnts, crs=self.crs), wdw=window_size
)
if zb.ndim > 1:
zb = zb.max(axis=1)

s["z"] = zb.values
if dz is not None:
s["z"] += float(dz)
structs_out.append(s)
gdf = utils.linestring2gdf(structs_out, crs=self.crs)
# Else function if you define elevation of weir
Expand Down
4 changes: 2 additions & 2 deletions hydromt_sfincs/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,9 +424,9 @@ def gdf2linestring(gdf: gpd.GeoDataFrame) -> List[Dict]:
feat = item.drop("geometry").dropna().to_dict()
# check geom
line = item.geometry
if line.type == "MultiLineString" and len(line.geoms) == 1:
if line.geom_type == "MultiLineString" and len(line.geoms) == 1:
line = line.geoms[0]
if line.type != "LineString":
if line.geom_type != "LineString":
raise ValueError("Invalid geometry type, only LineString is accepted.")
xyz = tuple(zip(*line.coords[:]))
feat["x"], feat["y"] = list(xyz[0]), list(xyz[1])
Expand Down
3 changes: 3 additions & 0 deletions tests/test_1model_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ def test_structs(tmpdir):
assert "weirfile" in mod.config
mod.write_geoms()
assert isfile(join(mod.root, "sfincs.weir"))
# test with buffer
mod.setup_structures(fn_thd_gis, stype="weir", buffer=5, dep="dep", merge=False)
assert len(mod.geoms["weir"].index) == 2


def test_drainage_structures(tmpdir):
Expand Down
Loading