Skip to content

Commit

Permalink
Merge branch 'dev' into bugfix/terrain-gen-failure
Browse files Browse the repository at this point in the history
  • Loading branch information
sclaw authored Jan 15, 2025
2 parents 1517c27 + 76c4633 commit f58d39c
Show file tree
Hide file tree
Showing 25 changed files with 2,818 additions and 8 deletions.
15 changes: 15 additions & 0 deletions ripple1d/conflate/rasfim.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from shapely.ops import linemerge, nearest_points, split, transform

from ripple1d.consts import METERS_PER_FOOT
from ripple1d.errors import BadConflation
from ripple1d.utils.ripple_utils import (
check_xs_direction,
clip_ras_centerline,
Expand Down Expand Up @@ -694,6 +695,19 @@ def map_reach_xs(rfc: RasFimConflater, reach: MultiLineString) -> dict:
return {"us_xs": us_data, "ds_xs": ds_data, "eclipsed": False}


def validate_reach_conflation(reach_xs_data: dict, reach_id: str):
"""Raise error for invalid conflation.
The trim_reach method in subset_gpkg.py will return an empty geodataframe when u/s xs_id is lower than d/s xs_id.
This likely indicates poor CRS inference.
"""
us = reach_xs_data["us_xs"]
ds = reach_xs_data["ds_xs"]
if (us["river"] == ds["river"]) & (us["reach"] == ds["reach"]) & (us["xs_id"] < ds["xs_id"]):
err_str = f"Reach {reach_id} has u/s xs station ({us['xs_id']}) lower than d/s xs station ({ds['xs_id']})"
raise BadConflation(err_str)


def ras_reaches_metadata(rfc: RasFimConflater, candidate_reaches: gpd.GeoDataFrame, river_reach_name: str):
"""Return the metadata for the RAS reaches."""
reach_metadata = OrderedDict()
Expand All @@ -702,6 +716,7 @@ def ras_reaches_metadata(rfc: RasFimConflater, candidate_reaches: gpd.GeoDataFra
try:
# get the xs data for the reach
ras_xs_data = map_reach_xs(rfc, reach)
validate_reach_conflation(ras_xs_data, str(reach.ID))
reach_metadata[reach.ID] = ras_xs_data
except Exception as e:
logging.error(f"river-reach: {river_reach_name} | network id: {reach.ID} | Error: {e}")
Expand Down
14 changes: 14 additions & 0 deletions ripple1d/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,17 @@ class UnknownVerticalUnits(Exception):

class RasTerrainFailure(Exception):
"""Raised when the HEC-RAS CreateTerrain executable fails to generate terrain."""


class NullTerrainError(Exception):
"""Raised when the downloaded terrain for an error is all nodata values."""


class BadConflation(Exception):
"""Raised when conflation yields a d/s cross-section with higher station than the u/s cross-section."""


class SingleXSModel(Exception):
"""Raised when geopackage creation would yield a single cross-section model."""


2 changes: 1 addition & 1 deletion ripple1d/ops/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ def compute_conflation_metrics(source_model_directory: str, source_network: dict
if conflation_parameters["reaches"][network_id]["eclipsed"] == True:
continue

rgs = RippleGeopackageSubsetter(src_gpkg_path, conflation_json, network_id)
rgs = RippleGeopackageSubsetter(src_gpkg_path, conflation_json, "", network_id)
layers = {}
for layer, gdf in rgs.subset_gdfs.items():
layers[layer] = gdf.to_crs(HYDROFABRIC_CRS)
Expand Down
6 changes: 3 additions & 3 deletions ripple1d/ops/ras_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ def get_flow_depth_arrays(

wse = wses.loc[river_reach_rs, :]
flow = flows.loc[river_reach_rs, :]
df = pd.DataFrame({"wse": wse.round(2), "flow": flow.round(2)}).drop_duplicates()
df = pd.DataFrame({"wse": wse.round(1), "flow": flow.astype(int)}).drop_duplicates()

# convert wse to depth
depth = df["wse"] - thalweg
Expand Down Expand Up @@ -381,8 +381,8 @@ def create_flow_depth_combinations(
"""
depths, flows, wses = [], [], []
for wse, depth in zip(ds_wses, ds_depths):
for flow in input_flows:
if depth >= min_depths.loc[str(int(flow))]:
for profile, flow in input_flows.items():
if depth >= min_depths.loc[profile]:
depths.append(round(depth, 1))
flows.append(int(max([flow, MIN_FLOW])))
wses.append(round(wse, 1))
Expand Down
10 changes: 7 additions & 3 deletions ripple1d/ops/subset_gpkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import ripple1d
from ripple1d.data_model import NwmReachModel, RippleSourceDirectory
from ripple1d.errors import SingleXSModel
from ripple1d.utils.ripple_utils import (
clip_ras_centerline,
fix_reversed_xs,
Expand Down Expand Up @@ -254,8 +255,9 @@ def subset_gdfs(self) -> dict:
subset_gdfs = {}
subset_gdfs["XS"] = self.subset_xs
if len(subset_gdfs["XS"]) <= 1: # check if only 1 cross section for nwm_reach
logging.warning(f"Only 1 cross section conflated to NWM reach {self.nwm_id}. Skipping this reach.")
return None
err_string = f"Sub model for {self.nwm_id} would have {len(subset_gdfs['XS'])} cross-sections but is not tagged as eclipsed. Skipping."
logging.warning(err_string)
raise SingleXSModel(err_string)
subset_gdfs["River"] = self.subset_river
if self.subset_structures is not None:
subset_gdfs["Structure"] = self.subset_structures
Expand Down Expand Up @@ -476,13 +478,15 @@ def extract_submodel(source_model_directory: str, submodel_directory: str, nwm_i
ripple1d_parameters["messages"] = f"skipping {nwm_id}; no cross sections conflated."
logging.warning(ripple1d_parameters["messages"])
gpkg_path = None
conflation_file = None

else:
rgs = RippleGeopackageSubsetter(rsd.ras_gpkg_file, rsd.conflation_file, submodel_directory, nwm_id)
rgs.write_ripple_gpkg()
ripple1d_parameters = rgs.update_ripple1d_parameters(rsd)
rgs.write_ripple1d_parameters(ripple1d_parameters)
gpkg_path = rgs.ripple_gpkg_file
conflation_file = rsd.conflation_file

logging.info(f"extract_submodel complete for nwm_id {nwm_id}")
return {"ripple1d_parameters": rsd.conflation_file, "ripple_gpkg_file": gpkg_path}
return {"ripple1d_parameters": conflation_file, "ripple_gpkg_file": gpkg_path}
6 changes: 5 additions & 1 deletion ripple1d/utils/dg_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from shapely import Polygon

from ripple1d.consts import METERS_PER_FOOT
from ripple1d.errors import UnknownVerticalUnits
from ripple1d.errors import NullTerrainError, UnknownVerticalUnits

from .s3_utils import *

Expand Down Expand Up @@ -176,6 +176,10 @@ def clip_raster(src_path: str, dst_path: str, mask_polygon: Polygon, vertical_un
with rasterio.open(src_path) as src:
out_meta = src.meta
out_image, out_transform = mask.mask(src, [mask_polygon], all_touched=True, crop=True)
nd = src.nodata

if np.all(out_image == nd):
raise NullTerrainError(f"Terrain downloaded from {src_path} was all nodata values.")

out_meta.update(
{
Expand Down
41 changes: 41 additions & 0 deletions tests/rounding_error_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import os
import time

import psutil

from ripple1d.ops.ras_run import run_known_wse

TIMEOUT = 60
WAIT_TIME = 0.1


def wait_for_process(pid: int):
run_time = 0
while psutil.pid_exists(pid):
if run_time < TIMEOUT:
time.sleep(WAIT_TIME)
run_time += WAIT_TIME
else:
psutil.Process(pid).terminate()
raise RuntimeError("RAS run timed out.")


def test_kwse_run():
"""Check that problematic model runs with no errors."""
model_dir = os.path.join(os.path.dirname(__file__), "test-data", "14320639")
payload = {
"submodel_directory": model_dir,
"plan_suffix": "kwse",
"show_ras": True,
"write_depth_grids": False,
"min_elevation": 182.2,
"max_elevation": 194.1,
"depth_increment": 1,
}
result = run_known_wse(**payload)
wait_for_process(int(result["pid"]))
[os.remove(os.path.join(model_dir, f)) for f in os.listdir(model_dir) if f.endswith("03") or f.endswith("03.hdf")]


if __name__ == "__main__":
test_kwse_run()
Binary file added tests/test-data/14320639/14320639.O01
Binary file not shown.
Binary file added tests/test-data/14320639/14320639.O02
Binary file not shown.
209 changes: 209 additions & 0 deletions tests/test-data/14320639/14320639.f01
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
Flow Title=14320639_ind
Number of Profiles= 50
Profile Names=53874,69241,84608,99975,115342,130710,146077,161444,176811,192179,207546,222913,238280,253647,269015,284382,299749,315116,330484,345851,361218,376585,391952,407320,422687,438054,453421,468789,484156,499523,514890,530257,545625,560992,576359,591726,607094,622461,637828,653195,668562,683930,699297,714664,730031,745399,760766,776133,791500,806868
River Rch & RM=14320639,14320639 ,5.0
53874 69241 84608 99975 115342 130710 146077 161444 176811 192179
207546 222913 238280 253647 269015 284382 299749 315116 330484 345851
361218 376585 391952 407320 422687 438054 453421 468789 484156 499523
514890 530257 545625 560992 576359 591726 607094 622461 637828 653195
668562 683930 699297 714664 730031 745399 760766 776133 791500 806868
Boundary for River Rch & Prof#=14320639,14320639 , 1
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 2
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 3
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 4
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 5
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 6
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 7
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 8
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 9
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 10
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 11
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 12
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 13
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 14
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 15
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 16
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 17
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 18
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 19
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 20
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 21
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 22
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 23
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 24
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 25
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 26
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 27
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 28
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 29
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 30
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 31
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 32
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 33
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 34
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 35
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 36
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 37
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 38
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 39
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 40
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 41
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 42
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 43
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 44
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 45
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 46
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 47
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 48
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 49
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Boundary for River Rch & Prof#=14320639,14320639 , 50
Up Type= 0
Dn Type= 3
Dn Slope=0.001
Loading

0 comments on commit f58d39c

Please sign in to comment.