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

Small Model updates #534

Merged
merged 7 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
12 changes: 6 additions & 6 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,10 @@ Setup methods
GridModel.setup_maps_from_rasterdataset
GridModel.setup_maps_from_raster_reclass
GridModel.setup_grid
GridModel.setup_grid_from_constant
GridModel.setup_grid_from_rasterdataset
GridModel.setup_grid_from_raster_reclass
GridModel.setup_grid_from_geodataframe
GridModel.setup_grid_data_from_constant
GridModel.setup_grid_data_from_rasterdataset
GridModel.setup_grid_data_from_raster_reclass
GridModel.setup_grid_data_from_geodataframe


.. _lumped_model_api:
Expand Down Expand Up @@ -369,8 +369,8 @@ Setup methods
MeshModel.setup_config
MeshModel.setup_region
MeshModel.setup_mesh2d
MeshModel.setup_mesh2d_from_rasterdataset
MeshModel.setup_mesh2d_from_raster_reclass
MeshModel.setup_mesh2d_data_from_rasterdataset
MeshModel.setup_mesh2d_data_from_raster_reclass
MeshModel.setup_maps_from_rasterdataset
MeshModel.setup_maps_from_raster_reclass

Expand Down
3 changes: 3 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ Added
- Added documentation for how to start your own plugin (PR #446)
- New raster method ``to_slippy_tiles``: tiling of a raster dataset according to the slippy tile structure for e.g., webviewers (PR #440).
- Support for http and other *filesystems* in path of data source (PR #515).
- ``set_forcing`` can now add pandas.DataFrame object to frocing. (PR #534)

Changed
-------
- Updated ``MeshModel`` and related methods to support multigrids instead of one single 2D grid. (PR #412)
- Updated generic setup grid and mesh2d functions names to distinguish better if they add data or create schematisation. (PR #534)
- possibility to ``load`` the data in the model read_ functions for netcdf files (default for read_grid in r+ mode). (PR #460)
- Internal model components (e.g. `Models._maps`, `GridModel._grid``) are now initialized with None and should not be accessed directly,
call the corresponding model property (e.g. `Model.maps`, `GridModel.grid`) instead. (PR #473)
Expand All @@ -41,6 +43,7 @@ Fixed
-----
- when a model component (eg maps, forcing, grid) is updated using the set_ methods, it will first be read to avoid loosing data. (PR #460)
- open_geodataset with driver vector also works for other geometry type than points. (PR #509)
- overwrite model in update mode. (PR #534)

Deprecated
----------
Expand Down
4 changes: 2 additions & 2 deletions docs/dev/plugin-quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ Using HydroMT generic methods, for your user, the build configuration file would

.. code-block:: yaml

setup_grid_from_rasterdataset:
setup_grid_data_from_rasterdataset:
raster_fn: vito
fill_method: nearest
reproject_method: mode
rename:
vito: landuse

setup_grid_from_raster_reclass:
setup_grid_data_from_raster_reclass:
raster_fn: vito
reclass_table_fn: vito_reclass
reclass_variables:
Expand Down
12 changes: 6 additions & 6 deletions examples/grid_model_build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ setup_grid:
basin_index_fn: merit_hydro_index
hydrography_fn: merit_hydro

setup_grid_from_constant:
setup_grid_data_from_constant:
constant: 0.01
name: c1
dtype: float32
nodata: -99.0

setup_grid_from_rasterdataset:
setup_grid_data_from_rasterdataset:
raster_fn: merit_hydro_1k
variables:
- elevtn
Expand All @@ -25,22 +25,22 @@ setup_grid_from_rasterdataset:
- average
- mode

setup_grid_from_rasterdataset2:
setup_grid_data_from_rasterdataset2:
raster_fn: vito
fill_method: nearest
reproject_method: mode
rename:
vito: landuse

setup_grid_from_raster_reclass:
setup_grid_data_from_raster_reclass:
raster_fn: vito
reclass_table_fn: vito_reclass
reclass_variables:
- manning
reproject_method:
- average

setup_grid_from_geodataframe:
setup_grid_data_from_geodataframe:
vector_fn: hydro_lakes
variables:
- waterbody_id
Expand All @@ -53,7 +53,7 @@ setup_grid_from_geodataframe:
waterbody_id: lake_id
Detph_avg: lake_depth

setup_grid_from_geodataframe2:
setup_grid_data_from_geodataframe2:
vector_fn: hydro_lakes
rasterize_method: fraction
rename:
Expand Down
6 changes: 3 additions & 3 deletions examples/working_with_models.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@
"source": [
"We can setup maps data using the ``setup_maps_from_raster`` and ``setup_maps_from_raster_reclass`` methods. Both methods add data to the **maps** component based on input raster data (RasterDataset type), but the second method additionally reclassifies the input data based on a reclassification table. The **maps** component gathers any raster input data without any requirements for a specific grid (CRS and resolution). It can contain, for example, direct model input data for models like Delft3D-FM that will interpolate input data on the fly to the model mesh, or auxiliary data that are not used by the model kernel but can be used by HydroMT to build the model (e.g. a gridded DEM), etc.\n",
"\n",
"For models that require all their input data to be resampled to the exact computation grid (all raster at the same resolution and projection), then the input data would go into the **grid** component. The corresponding ``setup_grid_from_raster`` and ``setup_grid_from_raster_reclass`` functions for the **grid** components are also available.\n",
"For models that require all their input data to be resampled to the exact computation grid (all raster at the same resolution and projection), then the input data would go into the **grid** component. The corresponding ``setup_grid_data_from_raster`` and ``setup_grid_data_from_raster_reclass`` functions for the **grid** components are also available.\n",
"\n",
"But back to our example, let's add both a DEM map from the data source *merit_hydro_1k* and a manning roughness map based on reclassified landuse data from the *vito* dataset to our model grid object."
]
Expand All @@ -278,14 +278,14 @@
"metadata": {},
"outputs": [],
"source": [
"mod.setup_grid_from_rasterdataset(\n",
"mod.setup_grid_data_from_rasterdataset(\n",
" raster_fn=\"merit_hydro_1k\",\n",
" variables=\"elevtn\",\n",
" fill_method=None,\n",
" reproject_method=\"bilinear\",\n",
" rename={\"elevtn\": \"DEM\"},\n",
")\n",
"mod.setup_grid_from_raster_reclass(\n",
"mod.setup_grid_data_from_raster_reclass(\n",
" raster_fn=\"vito\",\n",
" fill_method=\"nearest\",\n",
" reclass_table_fn=\"vito_reclass\", # Note: from local data catalog\n",
Expand Down
10 changes: 5 additions & 5 deletions examples/working_with_models_basics.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,10 @@
"source": [
"In this configuration, you see that we will prepare quite a lot of data for our grid model using some of the generic model methods for grid. We will prepare:\n",
"\n",
"- A grid with constant values 0.01 using [setup_grid_from_constant](https://deltares.github.io/hydromt/latest/_generated/hydromt.GridModel.setup_grid_from_constant.html)\n",
"- A couple of grid based on reprojection of MERIT Hydro IHU (elevation, basins) and VITO (landuse) using [setup_grid_from_rasterdataset](https://deltares.github.io/hydromt/latest/_generated/hydromt.GridModel.setup_grid_from_rasterdataset.html). Note that to use the same method twice within the same configuration file, you can end the method name with a number.\n",
"- A grid generated by mapping roughness values to the land use classes in VITO using [setup_grid_from_raster_reclass](https://deltares.github.io/hydromt/latest/_generated/hydromt.GridModel.setup_grid_from_raster_reclass.html)\n",
"- A couple of lake properties including the fraction of the grid cells covered by the lake geometry using [setup_grid_from_geodataframe](https://deltares.github.io/hydromt/latest/_generated/hydromt.GridModel.setup_grid_from_geodataframe.html)"
"- A grid with constant values 0.01 using [setup_grid_data_from_constant](https://deltares.github.io/hydromt/latest/_generated/hydromt.GridModel.setup_grid_data_from_constant.html)\n",
"- A couple of grid based on reprojection of MERIT Hydro IHU (elevation, basins) and VITO (landuse) using [setup_grid_data_from_rasterdataset](https://deltares.github.io/hydromt/latest/_generated/hydromt.GridModel.setup_grid_data_from_rasterdataset.html). Note that to use the same method twice within the same configuration file, you can end the method name with a number.\n",
"- A grid generated by mapping roughness values to the land use classes in VITO using [setup_grid_data_from_raster_reclass](https://deltares.github.io/hydromt/latest/_generated/hydromt.GridModel.setup_grid_data_from_raster_reclass.html)\n",
"- A couple of lake properties including the fraction of the grid cells covered by the lake geometry using [setup_grid_data_from_geodataframe](https://deltares.github.io/hydromt/latest/_generated/hydromt.GridModel.setup_grid_data_from_geodataframe.html)"
]
},
{
Expand Down Expand Up @@ -297,7 +297,7 @@
"outputs": [],
"source": [
"%%writefile ./tmp_grid_model1/grid_model_update.yaml\n",
"setup_grid_from_rasterdataset:\n",
"setup_grid_data_from_rasterdataset:\n",
" raster_fn: merit_hydro_1k\n",
" variables: uparea\n",
" reproject_method: max\n",
Expand Down
16 changes: 13 additions & 3 deletions hydromt/models/model_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,10 @@ def update(
'"model_out" directory required when updating in "read-only" mode'
)
self.read()
self.set_root(model_out, mode="w")
if forceful_overwrite:
self.set_root(model_out, mode="w+")
else:
self.set_root(model_out, mode="w")

# check if model has a region
if self.region is None:
Expand Down Expand Up @@ -1335,21 +1338,28 @@ def forcing(self) -> Dict[str, Union[xr.Dataset, xr.DataArray]]:

def set_forcing(
self,
data: Union[xr.DataArray, xr.Dataset],
data: Union[xr.DataArray, xr.Dataset, pd.DataFrame],
name: Optional[str] = None,
split_dataset: Optional[bool] = True,
):
"""Add data to forcing attribute.

Data can be xarray.DataArray, xarray.Dataset or pandas.DataFrame.
If pandas.DataFrame, indices should be the DataFrame index and the columns
the variable names. the DataFrame will then be converted to xr.Dataset using
:py:meth:`pandas.DataFrame.to_xarray` method.

Arguments
---------
data: xarray.Dataset or xarray.DataArray
data: xarray.Dataset or xarray.DataArray or pd.DataFrame
New forcing data to add
name: str, optional
Results name, required if data is xarray.Dataset is and split_dataset=False.
split_dataset: bool, optional
If True (default), split a Dataset to store each variable as a DataArray.
"""
if isinstance(data, pd.DataFrame):
data = data.to_xarray()
data_dict = _check_data(data, name, split_dataset)
for name in data_dict:
if name in self.forcing: # trigger init / read
Expand Down
10 changes: 5 additions & 5 deletions hydromt/models/model_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def __init__(self, *args, **kwargs) -> None:
self._grid = None # xr.Dataset()

# generic grid methods
def setup_grid_from_constant(
def setup_grid_data_from_constant(
self,
constant: Union[int, float],
name: str,
Expand Down Expand Up @@ -73,7 +73,7 @@ def setup_grid_from_constant(

return [name]

def setup_grid_from_rasterdataset(
def setup_grid_data_from_rasterdataset(
self,
raster_fn: Union[str, Path, xr.DataArray, xr.Dataset],
variables: Optional[List] = None,
Expand Down Expand Up @@ -143,7 +143,7 @@ def setup_grid_from_rasterdataset(

return list(ds_out.data_vars.keys())

def setup_grid_from_raster_reclass(
def setup_grid_data_from_raster_reclass(
self,
raster_fn: Union[str, Path, xr.DataArray],
reclass_table_fn: Union[str, Path, pd.DataFrame],
Expand Down Expand Up @@ -231,7 +231,7 @@ def setup_grid_from_raster_reclass(

return list(ds_vars.data_vars.keys())

def setup_grid_from_geodataframe(
def setup_grid_data_from_geodataframe(
self,
vector_fn: Union[str, Path, gpd.GeoDataFrame],
variables: Optional[Union[List, str]] = None,
Expand Down Expand Up @@ -291,7 +291,7 @@ def setup_grid_from_geodataframe(
if gdf.empty:
self.logger.warning(
f"No shapes of {vector_fn} found within region,"
" skipping setup_grid_from_vector."
" skipping setup_grid_data_from_geodataframe."
)
return
# Data resampling
Expand Down
4 changes: 2 additions & 2 deletions hydromt/models/model_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(self, *args, **kwargs) -> None:
self._mesh = None

## general setup methods
def setup_mesh2d_from_rasterdataset(
def setup_mesh2d_data_from_rasterdataset(
self,
raster_fn: Union[str, Path, xr.DataArray, xr.Dataset],
grid_name: Optional[str] = "mesh2d",
Expand Down Expand Up @@ -112,7 +112,7 @@ def setup_mesh2d_from_rasterdataset(

return list(ds_sample.data_vars.keys())

def setup_mesh2d_from_raster_reclass(
def setup_mesh2d_data_from_raster_reclass(
self,
raster_fn: Union[str, Path, xr.DataArray],
reclass_table_fn: Union[str, Path, pd.DataFrame],
Expand Down
21 changes: 12 additions & 9 deletions tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ def test_model_append(demda, df, tmpdir):
assert "dem" in mod1.maps
mod1.set_forcing(demda, name="dem1")
assert "dem" in mod1.forcing
mod1.set_forcing(df, name="df1", split_dataset=False)
assert "df1" in mod1.forcing
assert isinstance(mod1.forcing["df1"], xr.Dataset)
mod1.set_states(demda, name="dem1")
assert "dem" in mod1.states
mod1.set_geoms(demda.raster.box, name="dem1")
Expand Down Expand Up @@ -524,44 +527,44 @@ def test_gridmodel_setup(tmpdir):
add_mask=True,
)
# Add data with setup_* methods
mod.setup_grid_from_constant(
mod.setup_grid_data_from_constant(
constant=0.01,
name="c1",
nodata=-99.0,
)
mod.setup_grid_from_constant(
mod.setup_grid_data_from_constant(
constant=2,
name="c2",
dtype=np.int8,
nodata=-1,
)
mod.setup_grid_from_rasterdataset(
mod.setup_grid_data_from_rasterdataset(
raster_fn="merit_hydro",
variables=["elevtn", "basins"],
reproject_method=["average", "mode"],
mask_name="mask",
)
mod.setup_grid_from_rasterdataset(
mod.setup_grid_data_from_rasterdataset(
raster_fn="vito",
fill_method="nearest",
reproject_method="mode",
rename={"vito": "landuse"},
)
mod.setup_grid_from_raster_reclass(
mod.setup_grid_data_from_raster_reclass(
raster_fn="vito",
fill_method="nearest",
reclass_table_fn="vito_mapping",
reclass_variables=["roughness_manning"],
reproject_method=["average"],
)
mod.setup_grid_from_geodataframe(
mod.setup_grid_data_from_geodataframe(
vector_fn="hydro_lakes",
variables=["waterbody_id", "Depth_avg"],
nodata=[-1, -999.0],
rasterize_method="value",
rename={"waterbody_id": "lake_id", "Depth_avg": "lake_depth"},
)
mod.setup_grid_from_geodataframe(
mod.setup_grid_data_from_geodataframe(
vector_fn="hydro_lakes",
rasterize_method="fraction",
rename={"hydro_lakes": "water_frac"},
Expand Down Expand Up @@ -712,9 +715,9 @@ def test_meshmodel_setup(griduda, world):
region = {"mesh": griduda}
mod1 = MeshModel(data_libs=["artifact_data", dc_param_fn])
mod1.setup_mesh2d(region, grid_name="mesh2d")
mod1.setup_mesh2d_from_rasterdataset("vito", grid_name="mesh2d")
mod1.setup_mesh2d_data_from_rasterdataset("vito", grid_name="mesh2d")
assert "vito" in mod1.mesh.data_vars
mod1.setup_mesh2d_from_raster_reclass(
mod1.setup_mesh2d_data_from_raster_reclass(
raster_fn="vito",
reclass_table_fn="vito_mapping",
reclass_variables=["roughness_manning"],
Expand Down
Loading