Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
132 commits
Select commit Hold shift + click to select a range
554ef25
initial refactor of suppPrecipMod.py
mdeshotel Mar 29, 2026
48cd232
add doc strings
mdeshotel Mar 29, 2026
d3a1af8
make _initialize_config_options a private method and increase verbosi…
mdeshotel Mar 30, 2026
01fd462
check if attibute allready exists
mdeshotel Mar 30, 2026
6306463
add comment for initializing attributes to none
mdeshotel Mar 30, 2026
23059c6
fix manual caching of properties
mdeshotel Apr 8, 2026
b59b83b
Fix broken symbol reference
mxkpp Aug 10, 2026
20a5527
Fix issues with handling of setters/getters, properties, usage of con…
mxkpp Aug 10, 2026
6212790
Add keys to supp precip expected test data
mxkpp Aug 10, 2026
696e1af
Tests: add flexibility for equality assertions of keys "_coords", "la…
mxkpp Aug 11, 2026
01e9b41
Format
mxkpp Aug 11, 2026
e901ecd
Tests: when performing equality tests (with tolerance) for a given ke…
mxkpp Aug 11, 2026
244f9f1
Tests data: handle negative sign after hash sentinel
mxkpp Aug 11, 2026
8458c82
use projected crs instead of silencing warning from geographic crs use
mdeshotel Jun 25, 2026
d3f1393
fix doc string
mdeshotel Jun 25, 2026
95712f8
adjust buffer to account for 4km NWM resolution
mdeshotel Aug 4, 2026
c1cb076
use domain specific projected CRS
mdeshotel Aug 4, 2026
cb5691f
Temporary CRS for making a buffered mask: use dynamic UTM CRS for Haw…
mxkpp Aug 7, 2026
c1cfd43
Test data: include new centroid key and update for new mask buffer logic
mxkpp Aug 14, 2026
67b2358
Explicit cleanup call on BMI finalize()
idtodd Jun 10, 2026
64dca62
Simplify broadcast_parameter to use bcast
idtodd Jul 14, 2026
72be130
Remove use of err_handler.err_out
idtodd Jul 14, 2026
baaf864
Documentation updates
idtodd Jul 14, 2026
f817a33
Always use default ConfigOptions for messaging
idtodd Jul 14, 2026
283c24f
Intercomm/Intracomm mixup
idtodd Aug 3, 2026
3033779
Reintroduce atexit cleanup for signal handling
idtodd Aug 6, 2026
ef17cb4
Update a commented-out block
mxkpp Aug 7, 2026
4da06a7
add type hints; rename vars
mdeshotel Jul 15, 2026
90616b3
Deprecate forecastMod.py
mxkpp Aug 11, 2026
e6f1f13
move consts to consts.py
mdeshotel May 5, 2026
1f4288e
break intialize method into properties with setters to validate.
mdeshotel May 5, 2026
3bbfe2a
fix setter logic; update doc strings
mdeshotel May 13, 2026
8cb6a8d
fix circular imports
mdeshotel May 18, 2026
38b2cf6
updat for NHF
mdeshotel May 18, 2026
7250326
remove calls to validate_config and initialize
mdeshotel May 18, 2026
6c1a680
debugging changes
mdeshotel May 18, 2026
88146fc
handle circular imports
mdeshotel May 19, 2026
786cffd
remove commented out attributes
mdeshotel May 19, 2026
af922e0
use dir instead of vars
mdeshotel May 19, 2026
91550d0
debugging
mdeshotel May 19, 2026
6ac79f0
fix regrid_opt
mdeshotel May 20, 2026
5ba2579
refactor initialize method
mdeshotel May 27, 2026
9f615dc
remove excessive code comments
mdeshotel May 28, 2026
2b1cf0c
move init none attrs to consts.py
mdeshotel Jun 26, 2026
57ce76c
merge bmi_model refactor
mdeshotel Jul 1, 2026
3f66d53
Simplify var passing within NWMv3ForcingEngineModel.run
mxkpp Apr 24, 2026
65d9e1f
Raise error on unexpected grid_type
mxkpp Apr 27, 2026
e7eb5b1
Use `time.perf_counter` instead of `time.time`
mxkpp Apr 27, 2026
7e64e3f
Start encapsulating BMI model into model.py NWMv3ForcingEngineModel s…
mxkpp Apr 27, 2026
e7d92b9
Encapsulate ConfigOptions instance
mxkpp Apr 27, 2026
cbe2197
Encapsulate GeoMeta instance
mxkpp Apr 27, 2026
98ce2af
Encapsulate input forcing mod dict
mxkpp Apr 27, 2026
433d180
Encapsulate supp pcp mod
mxkpp Apr 27, 2026
105547c
Encapsulate MpiConfig
mxkpp Apr 27, 2026
5fbf642
Encapsulate OutputObj instance
mxkpp Apr 27, 2026
f37216f
Remove unused imports
mxkpp Apr 27, 2026
0ac49fe
Remove hard-coded msg control
mxkpp Apr 27, 2026
d4e283f
DRYify some AnA deltas
mxkpp Apr 27, 2026
1576417
DRYify calls to check_program_status
mxkpp Apr 27, 2026
b1ddfcd
Clean up comments and docstrings
mxkpp Apr 27, 2026
2e37210
Add forcing key count assertion
mxkpp Apr 29, 2026
034a3df
Update docstrings
mxkpp Apr 29, 2026
84a21c6
Move block using `rstFlag` to new private method
mxkpp Apr 29, 2026
5ab9812
Move block for supplemental precip handling to new private method
mxkpp Apr 29, 2026
7f8eead
docstrings and type hints
mxkpp Apr 29, 2026
5fcef77
Move block for AORC and NWM handling to new private method
mxkpp Apr 29, 2026
2cb35bb
Comments and type hints
mxkpp Apr 29, 2026
04a4db5
Move model.py BMI variables to consts.py
mxkpp Apr 29, 2026
361087a
Fix usage of new consts.MODEL list
mxkpp Apr 29, 2026
e2ce719
Comments
mxkpp Apr 29, 2026
06f2d87
Add NotImplementedError for SubOutputHour
mxkpp Apr 30, 2026
a3cfee1
Type hints and docstrings
mxkpp May 1, 2026
2d5be5e
Rename methods
mxkpp May 1, 2026
ec356bf
Fix input_forcings reference (return None conditionally)
mxkpp May 1, 2026
9d287dd
Use partials for log calls and use MPI-aware log methods
mxkpp May 2, 2026
9304958
Run flynt -tc -ll 9999
mxkpp May 2, 2026
b3a472a
Format docstrings to reST
mxkpp May 2, 2026
b9c6850
DRYify
mxkpp May 2, 2026
6cf6a1f
Add assertion
mxkpp May 2, 2026
b2cefbf
Fix source_data_processor sets
mxkpp May 2, 2026
b27beb3
Docstrings
mxkpp May 2, 2026
281c88d
comment out not implemented error.
mdeshotel Jul 13, 2026
4424fb9
Remove duplicate method
mxkpp Aug 13, 2026
2368e02
Following refactor+rebase: update CAT-ID assignments and init calls, …
mxkpp Aug 17, 2026
e79516c
Ruff reorder imports
mxkpp Aug 17, 2026
272bb15
Tests: update for new BMI forcing initialization method
mxkpp Aug 17, 2026
afc9964
Tests: improve test data serialization/deserialization logic
mxkpp Aug 17, 2026
9ae1dfe
Tests: bmi_model: exclude more keys
mxkpp Aug 17, 2026
be3ac8e
Fix various config handling issues following refactor + rebase. Notab…
mxkpp Aug 18, 2026
49b4579
Test data: update expected json files for bmi_model and config_option…
mxkpp Aug 18, 2026
4ab14e5
Bolster test utils handling of serialization and deserialization
mxkpp Aug 18, 2026
2d9b404
Format with ruff default line length (88)
mxkpp Aug 18, 2026
da09922
Adjustments following review
mxkpp Aug 18, 2026
3977f4b
Fix NameError during handling of class init args introduced during re…
mxkpp Aug 25, 2026
28043b2
Add short-circuit guard for property perform_downscaling to return Fa…
mxkpp Aug 25, 2026
f512c55
Remove vestigial self.GeoMeta attribute
mxkpp Aug 25, 2026
c47db3a
Add TODOs about potential bugs
mxkpp Aug 25, 2026
35ea0f9
Replace hard-coded supplemental precip count with dynamic length look…
mxkpp Aug 25, 2026
0ca29ce
Add targeted hardening of ConfigOptions attrs to address concerns doc…
mxkpp Aug 25, 2026
d94cd2d
Remove unused variable
mxkpp Aug 25, 2026
30e907a
Clean up docstrings
mxkpp Aug 26, 2026
ddb37fd
Fix key names for "NWM_Geogrid" and "RqiThreshold"
mxkpp Aug 26, 2026
dcd396c
Re-add GRIB2_CFS to file_types list
mxkpp Aug 26, 2026
ca02ea1
Fix key names "HGTVAR" and "HGTVAR_ELEM"
mxkpp Aug 26, 2026
c0c770e
Fix type for cfsv2EnsMember validation. Add defensive type checking t…
mxkpp Aug 26, 2026
39fb626
Fix order of validation call when building supp_precip_dirs for the E…
mxkpp Aug 26, 2026
5bfaff9
Handle None fcst_input_horizons for precip-only configs
mxkpp Aug 26, 2026
cb66dd3
Add length assertions for SuppPcpMandatory, RegridOptSuppPcp, SuppPcp…
mxkpp Aug 26, 2026
4aee11e
Initialize more vars (required for certain workflows)
mxkpp Aug 26, 2026
9227b6b
Better handling of SuppPcpMaxHours list
mxkpp Aug 26, 2026
7f973ef
spatial_meta setter: handle None
mxkpp Aug 26, 2026
e412d87
runCfsNldasBiasCorrect: add short-circuit for "precip only" case
mxkpp Aug 26, 2026
7b28b3d
Validate that supp precip time offsets are non-negative
mxkpp Aug 26, 2026
be98251
Minor improvements: avoid setting _regrid_opt unnecessarily; return N…
mxkpp Aug 26, 2026
4404501
To match original behavior, assert that output_freq and fcst_freq are…
mxkpp Aug 26, 2026
29de25d
Add backing var for _input_force_types to avoid potential crash under…
mxkpp Aug 26, 2026
bfa47b0
Handle a precip-only edge case restriction on configuration
mxkpp Aug 26, 2026
63a336f
Fix attribute access typo
mxkpp Aug 26, 2026
f7b964e
Raise error if non-hydrofabric discretization type (grid_type) is use…
mxkpp Aug 26, 2026
edd6a5e
Fix crashing method calls
mxkpp Aug 26, 2026
ed9b65f
Fix log calls
mxkpp Aug 26, 2026
bf0ad5a
Tests data: Update expected json to add "GRIB2_CFS" to "file_types" list
mxkpp Aug 26, 2026
d54eb32
Refactor layeringMod.layer_final_forcings into abstract classes by di…
mxkpp Aug 18, 2026
45c18c5
Refactor layeringMod.layer_supplemental_forcing into abstract classes…
mxkpp Aug 19, 2026
01ec525
Docstrings and type hints
mxkpp Aug 22, 2026
8104c05
Docstrings
mxkpp Aug 22, 2026
9cd9e15
Add TYPE_CHECKING guard for imports that are purely for type hints
mxkpp Aug 24, 2026
7cf9a7a
Replace camelCase with snake_case
mxkpp Aug 24, 2026
31ae48d
Improve class name self-references to allow for potential future inhe…
mxkpp Aug 24, 2026
2bddeea
Refactor timeInterpMod.py
mxkpp Aug 21, 2026
3efe9e8
Add README for 2026 refactor
mxkpp Aug 27, 2026
66004b6
Revise README_refactor_2026.md
mxkpp Aug 27, 2026
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
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import argparse
import os
import pathlib
import uuid

import geopandas as gpd
import netCDF4
import numpy as np
import pandas as pd
import argparse
import pathlib
import os
import uuid

gpd.options.display_precision = 16
np.set_printoptions(precision=128)
Expand Down Expand Up @@ -33,7 +34,7 @@ def convert_hyfab_to_esmf(hyfab_gpkg: pathlib.Path, esmf_mesh_output: pathlib.Pa
# for orientation properties since there are issues
# with geopandas for converting crs and translating
# orientation of polygon from original dataset
hyfab_cart = gpd.read_file(hyfab_gpkg, layer='divides')
hyfab_cart = gpd.read_file(hyfab_gpkg, layer="divides")
hyfab_cart = hyfab_cart.sort_values(by=["div_id"]).reset_index(drop=True)
hyfab = hyfab_cart.to_crs("WGS84")

Expand All @@ -51,23 +52,25 @@ def convert_hyfab_to_esmf(hyfab_gpkg: pathlib.Path, esmf_mesh_output: pathlib.Pa
hyfab_coords[:, 1] = false_ids

# Sort data by feature id and reset index
hyfab['element_id'] = false_ids
hyfab_cart['element_id'] = false_ids
hyfab["element_id"] = false_ids
hyfab_cart["element_id"] = false_ids

# Get element count
element_count = len(hyfab.element_id)

# find the number of nodes in first element
# based on geometry type
if (hyfab.geometry[0].geom_type == "Polygon"):
if hyfab.geometry[0].geom_type == "Polygon":
dup_df = pd.DataFrame([])
dup_df['node_x'], dup_df['node_y'] = hyfab.geometry[0].exterior.coords.xy
dup_df = dup_df.drop_duplicates(subset=['node_x', 'node_y'], keep='first')
dup_df["node_x"], dup_df["node_y"] = hyfab.geometry[0].exterior.coords.xy
dup_df = dup_df.drop_duplicates(subset=["node_x", "node_y"], keep="first")
elem_max_nodes = len(dup_df)
else:
dup_df = pd.DataFrame([])
dup_df['node_x'], dup_df['node_y'] = hyfab.geometry[0].geoms._get_geom_item(0).exterior.xy
dup_df = dup_df.drop_duplicates(subset=['node_x', 'node_y'], keep='first')
dup_df["node_x"], dup_df["node_y"] = (
hyfab.geometry[0].geoms._get_geom_item(0).exterior.xy
)
dup_df = dup_df.drop_duplicates(subset=["node_x", "node_y"], keep="first")
elem_max_nodes = len(dup_df)

# Allocate element arrays for center point calculations
Expand All @@ -84,15 +87,17 @@ def convert_hyfab_to_esmf(hyfab_gpkg: pathlib.Path, esmf_mesh_output: pathlib.Pa
# based on geometry type
total_num_nodes = 0
for i in range(element_count):
if (hyfab.geometry[i].geom_type == "Polygon"):
if hyfab.geometry[i].geom_type == "Polygon":
dup_df = pd.DataFrame([])
dup_df['node_x'], dup_df['node_y'] = hyfab.geometry[i].exterior.coords.xy
dup_df = dup_df.drop_duplicates(subset=['node_x', 'node_y'], keep='first')
dup_df["node_x"], dup_df["node_y"] = hyfab.geometry[i].exterior.coords.xy
dup_df = dup_df.drop_duplicates(subset=["node_x", "node_y"], keep="first")
total_num_nodes += len(dup_df)
else:
dup_df = pd.DataFrame([])
dup_df['node_x'], dup_df['node_y'] = hyfab.geometry[i].geoms._get_geom_item(0).exterior.xy
dup_df = dup_df.drop_duplicates(subset=['node_x', 'node_y'], keep='first')
dup_df["node_x"], dup_df["node_y"] = (
hyfab.geometry[i].geoms._get_geom_item(0).exterior.xy
)
dup_df = dup_df.drop_duplicates(subset=["node_x", "node_y"], keep="first")
total_num_nodes += len(dup_df)

# assign current node id and allocate node arrays to extract
Expand All @@ -107,49 +112,60 @@ def convert_hyfab_to_esmf(hyfab_gpkg: pathlib.Path, esmf_mesh_output: pathlib.Pa
# flip node coordinates based on orientation of polygons
# from the original cartesian coordinate system
for i in range(element_count):
if (hyfab.geometry[i].geom_type == "Polygon"):
if hyfab.geometry[i].geom_type == "Polygon":
dup_df = pd.DataFrame([])
dup_df['node_x'], dup_df['node_y'] = hyfab.geometry[i].exterior.coords.xy
dup_df = dup_df.drop_duplicates(subset=['node_x', 'node_y'], keep='first')
dup_df["node_x"], dup_df["node_y"] = hyfab.geometry[i].exterior.coords.xy
dup_df = dup_df.drop_duplicates(subset=["node_x", "node_y"], keep="first")
node_x = dup_df.node_x.values
node_y = dup_df.node_y.values
ccw = hyfab_cart.geometry[i].exterior.is_ccw
else:
dup_df = pd.DataFrame([])
dup_df['node_x'], dup_df['node_y'] = hyfab.geometry[i].geoms._get_geom_item(0).exterior.xy
dup_df = dup_df.drop_duplicates(subset=['node_x', 'node_y'], keep='first')
dup_df["node_x"], dup_df["node_y"] = (
hyfab.geometry[i].geoms._get_geom_item(0).exterior.xy
)
dup_df = dup_df.drop_duplicates(subset=["node_x", "node_y"], keep="first")
node_x = dup_df.node_x.values
node_y = dup_df.node_y.values
ccw = hyfab_cart.geometry[i].geoms._get_geom_item(0).exterior.is_ccw

num_nodes = len(node_x)
element_num_nodes[i] = num_nodes
if (num_nodes > elem_max_nodes):
if num_nodes > elem_max_nodes:
elem_max_nodes = num_nodes

element_x_coord[i] = hyfab.geometry[i].centroid.coords.xy[0][0]
element_y_coord[i] = hyfab.geometry[i].centroid.coords.xy[1][0]

element_elevation[i] = hyfab.elevation_mean[i]
element_slope[i] = hyfab.slope1km_mean[i]
element_slope_azmuith[i] = hyfab.aspect_circmean[i] # NHF aspect is currently in radians, may need to be converted to degrees

if (ccw):
node_x_coord[node_start:node_start + num_nodes] = np.array(node_x, dtype=np.double)
node_y_coord[node_start:node_start + num_nodes] = np.array(node_y, dtype=np.double)
# NHF aspect is currently in radians, may need to be converted to degrees
element_slope_azmuith[i] = hyfab.aspect_circmean[i]

if ccw:
node_x_coord[node_start : node_start + num_nodes] = np.array(
node_x, dtype=np.double
)
node_y_coord[node_start : node_start + num_nodes] = np.array(
node_y, dtype=np.double
)
else:
node_x_coord[node_start:node_start + num_nodes] = np.array(np.concatenate([[node_x[0]], np.flip(node_x[1:])]), dtype=np.double)
node_y_coord[node_start:node_start + num_nodes] = np.array(np.concatenate([[node_y[0]], np.flip(node_y[1:])]), dtype=np.double)
node_x_coord[node_start : node_start + num_nodes] = np.array(
np.concatenate([[node_x[0]], np.flip(node_x[1:])]), dtype=np.double
)
node_y_coord[node_start : node_start + num_nodes] = np.array(
np.concatenate([[node_y[0]], np.flip(node_y[1:])]), dtype=np.double
)
node_start += num_nodes

# Assign node data to pandas dataframe
# and calculate the duplicate nodes throughout
# the hydrofabric geometry network
node_connectivity = pd.DataFrame([])
node_connectivity['node_x'] = node_x_coord
node_connectivity['node_y'] = node_y_coord
node_connectivity["node_x"] = node_x_coord
node_connectivity["node_y"] = node_y_coord

duplicates = node_connectivity[node_connectivity.duplicated(keep='first')]
duplicates = node_connectivity[node_connectivity.duplicated(keep="first")]

# Create array to assign duplicate nodes as
# zeroes, while creating unique ids for only
Expand All @@ -158,25 +174,27 @@ def convert_hyfab_to_esmf(hyfab_gpkg: pathlib.Path, esmf_mesh_output: pathlib.Pa
node_id_connectivity = np.empty(len(node_id), dtype=np.int32)
node_count = 1
for i in range(len(node_id)):
if (i in duplicates_index):
if i in duplicates_index:
node_id_connectivity[i] = 0
else:
node_id_connectivity[i] = node_count
node_count += 1

# Assign new node id network to dataframe
node_connectivity['node_id'] = node_id_connectivity
node_connectivity["node_id"] = node_id_connectivity

# calculate the node id network to include its duplicate ids
# for each instance of the node coordinates
ESMF_node_id_connectivity = node_connectivity.groupby(['node_x', 'node_y']).node_id.transform('max')
ESMF_node_id_connectivity = node_connectivity.groupby(
["node_x", "node_y"]
).node_id.transform("max")

node_connectivity['node_id_connectivity'] = ESMF_node_id_connectivity.values
node_connectivity["node_id_connectivity"] = ESMF_node_id_connectivity.values

node_connectivity_final = node_connectivity.node_id_connectivity.values

# Extract only the unique node id network and respective coordinates
node_connectivity = node_connectivity.drop_duplicates('node_id_connectivity')
node_connectivity = node_connectivity.drop_duplicates("node_id_connectivity")
node_count = len(node_connectivity)
node_x_coord_final = node_connectivity.node_x.values
node_y_coord_final = node_connectivity.node_y.values
Expand All @@ -189,7 +207,9 @@ def convert_hyfab_to_esmf(hyfab_gpkg: pathlib.Path, esmf_mesh_output: pathlib.Pa
end_index = 0
for i in range(element_count):
end_index += element_num_nodes[i]
elementConn[i, 0:element_num_nodes[i]] = node_connectivity_final[start_index:end_index]
elementConn[i, 0 : element_num_nodes[i]] = node_connectivity_final[
start_index:end_index
]
start_index = end_index

out_dir = os.path.dirname(esmf_mesh_output)
Expand All @@ -203,17 +223,21 @@ def convert_hyfab_to_esmf(hyfab_gpkg: pathlib.Path, esmf_mesh_output: pathlib.Pa
nc = netCDF4.Dataset(temp_path, "w", format="NETCDF4")
node_count_dim = nc.createDimension("nodeCount", node_count)
elem_count_dim = nc.createDimension("elementCount", element_count)
elem_conn_count_dim = nc.createDimension("connectionCount", len(node_connectivity_final))
elem_conn_count_dim = nc.createDimension(
"connectionCount", len(node_connectivity_final)
)
node_count_dim = nc.createDimension("coordDim", 2)
node_coords_var = nc.createVariable("nodeCoords", 'f8', ("nodeCount", "coordDim"))
node_coords_var = nc.createVariable("nodeCoords", "f8", ("nodeCount", "coordDim"))
node_coords_var.units = "degrees"
elem_id = nc.createVariable("element_id", "i4", "elementCount")
elem_id.long_name = "False 32-bit catchment IDs use for ESMF mesh generation"
elem_conn_var = nc.createVariable("elementConn", "i4", ("connectionCount"))
elem_conn_var.long_name = "Node Indices that define the element connectivity"
num_elem_conn_var = nc.createVariable("numElementConn", "i", "elementCount")
num_elem_conn_var.long_name = "Number of nodes per element"
center_coords_var = nc.createVariable("centerCoords", 'f8', ("elementCount", "coordDim"))
center_coords_var = nc.createVariable(
"centerCoords", "f8", ("elementCount", "coordDim")
)
center_coords_var.units = "degrees"
nc.gridType = "unstructured"
nc.version = "0.9"
Expand All @@ -224,7 +248,9 @@ def convert_hyfab_to_esmf(hyfab_gpkg: pathlib.Path, esmf_mesh_output: pathlib.Pa
slope_elem_var = nc.createVariable("Element_Slope", "f8", ("elementCount"))
slope_elem_var.long_name = "Catchment slope"
slope_elem_var.units = "meters"
slope_azi_elem_var = nc.createVariable("Element_Slope_Azmuith", "f8", ("elementCount"))
slope_azi_elem_var = nc.createVariable(
"Element_Slope_Azmuith", "f8", ("elementCount")
)
slope_azi_elem_var.long_name = "Catchment slope azmuith angle"
slope_azi_elem_var.units = "Degrees"
hgt_elem_var[:] = element_elevation
Expand Down Expand Up @@ -258,8 +284,14 @@ def convert_hyfab_to_esmf(hyfab_gpkg: pathlib.Path, esmf_mesh_output: pathlib.Pa
def get_options():
parser = argparse.ArgumentParser()

parser.add_argument('hyfab_gpkg', type=pathlib.Path, help="Hydrofabric geopackage file pathway")
parser.add_argument("esmf_mesh_output", type=pathlib.Path, help="File pathway to save ESMF netcdf mesh file for hydrofabric")
parser.add_argument(
"hyfab_gpkg", type=pathlib.Path, help="Hydrofabric geopackage file pathway"
)
parser.add_argument(
"esmf_mesh_output",
type=pathlib.Path,
help="File pathway to save ESMF netcdf mesh file for hydrofabric",
)

return parser.parse_args()

Expand Down
Loading
Loading