roms-tools 2.4.0__py3-none-any.whl → 2.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ci/environment-with-xesmf.yml +16 -0
- roms_tools/__init__.py +1 -1
- roms_tools/analysis/roms_output.py +339 -234
- roms_tools/analysis/utils.py +137 -0
- roms_tools/plot.py +353 -214
- roms_tools/regrid.py +154 -9
- roms_tools/setup/boundary_forcing.py +51 -37
- roms_tools/setup/datasets.py +129 -74
- roms_tools/setup/grid.py +32 -33
- roms_tools/setup/initial_conditions.py +30 -37
- roms_tools/setup/nesting.py +238 -64
- roms_tools/setup/river_forcing.py +256 -86
- roms_tools/setup/surface_forcing.py +40 -28
- roms_tools/setup/tides.py +10 -13
- roms_tools/setup/topography.py +27 -4
- roms_tools/setup/utils.py +28 -12
- roms_tools/tests/test_analysis/test_roms_output.py +299 -80
- roms_tools/tests/test_regrid.py +85 -2
- roms_tools/tests/test_setup/test_boundary_forcing.py +63 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zattrs +3 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zmetadata +3 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zattrs +2 -2
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zmetadata +8 -7
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/abs_time/.zattrs +1 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/dust/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/dust_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/iron/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/iron_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nhy/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nhy_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nox/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nox_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air_alt/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zattrs +2 -2
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zmetadata +2 -2
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/dust/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/iron/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nhy/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nox/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air_alt/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/grid.zarr/.zmetadata +2 -2
- roms_tools/tests/test_setup/test_data/grid.zarr/angle/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid.zarr/angle_coarse/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid.zarr/f/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid.zarr/h/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/grid.zarr/h/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid.zarr/lat_coarse/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid.zarr/lat_rho/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid.zarr/lat_u/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid.zarr/lat_v/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid.zarr/pm/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zmetadata +1 -1
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/angle/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/angle_coarse/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/f/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/h/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_coarse/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_rho/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_u/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_v/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_coarse/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_rho/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_u/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_v/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/pm/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/pn/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zmetadata +1 -1
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/salt/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/temp/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/u/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ubar/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/v/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/vbar/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zeta/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zmetadata +27 -1
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/nriver/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/nriver/.zattrs +6 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/nriver/0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_location/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/.zmetadata +27 -1
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/nriver/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/nriver/.zattrs +6 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/nriver/0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_location/.zattrs +1 -1
- roms_tools/tests/test_setup/test_initial_conditions.py +16 -0
- roms_tools/tests/test_setup/test_nesting.py +141 -104
- roms_tools/tests/test_setup/test_river_forcing.py +580 -266
- roms_tools/tests/test_setup/test_surface_forcing.py +47 -0
- roms_tools/tests/test_setup/test_validation.py +34 -2
- roms_tools/utils.py +11 -7
- roms_tools/vertical_coordinate.py +1 -0
- {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info}/METADATA +22 -11
- {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info}/RECORD +214 -206
- {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info}/WHEEL +1 -1
- {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info/licenses}/LICENSE +0 -0
- {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info}/top_level.txt +0 -0
|
@@ -5,22 +5,26 @@ from datetime import datetime
|
|
|
5
5
|
import textwrap
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
import pytest
|
|
8
|
+
import logging
|
|
8
9
|
from conftest import calculate_file_hash
|
|
9
|
-
from roms_tools.download import download_river_data
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
@pytest.fixture
|
|
13
|
-
def
|
|
14
|
-
|
|
15
|
-
grid = Grid(
|
|
13
|
+
def iceland_test_grid():
|
|
14
|
+
return Grid(
|
|
16
15
|
nx=18, ny=18, size_x=800, size_y=800, center_lon=-18, center_lat=65, rot=20, N=3
|
|
17
16
|
)
|
|
18
17
|
|
|
18
|
+
|
|
19
|
+
@pytest.fixture
|
|
20
|
+
def river_forcing_climatology(iceland_test_grid):
|
|
21
|
+
"""Fixture for creating a RiverForcing object from the global Dai river dataset."""
|
|
22
|
+
|
|
19
23
|
start_time = datetime(1998, 1, 1)
|
|
20
24
|
end_time = datetime(1998, 3, 1)
|
|
21
25
|
|
|
22
26
|
return RiverForcing(
|
|
23
|
-
grid=
|
|
27
|
+
grid=iceland_test_grid,
|
|
24
28
|
start_time=start_time,
|
|
25
29
|
end_time=end_time,
|
|
26
30
|
convert_to_climatology="always",
|
|
@@ -52,325 +56,635 @@ def river_forcing_for_grid_that_straddles_dateline():
|
|
|
52
56
|
)
|
|
53
57
|
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
@pytest.fixture
|
|
60
|
+
def single_cell_indices():
|
|
61
|
+
# These are the indices that the `river_forcing` fixture generates automatically.
|
|
62
|
+
return {
|
|
63
|
+
"Hvita(Olfusa)": [(8, 6)],
|
|
64
|
+
"Thjorsa": [(8, 6)],
|
|
65
|
+
"JkulsFjll": [(11, 12)],
|
|
66
|
+
"Lagarfljot": [(9, 13)],
|
|
67
|
+
"Bruara": [(8, 6)],
|
|
68
|
+
"Svarta": [(12, 9)],
|
|
69
|
+
}
|
|
57
70
|
|
|
58
|
-
|
|
59
|
-
|
|
71
|
+
|
|
72
|
+
@pytest.fixture
|
|
73
|
+
def multi_cell_indices():
|
|
74
|
+
# These are the indices that the `river_forcing` fixture generates automatically.
|
|
75
|
+
return {
|
|
76
|
+
"Hvita(Olfusa)": [(8, 6)],
|
|
77
|
+
"Thjorsa": [(8, 6)],
|
|
78
|
+
"JkulsFjll": [(11, 12)],
|
|
79
|
+
"Lagarfljot": [(9, 13), (10, 13)],
|
|
80
|
+
"Bruara": [(8, 6)],
|
|
81
|
+
"Svarta": [(12, 8), (12, 9), (12, 10)],
|
|
82
|
+
}
|
|
60
83
|
|
|
61
84
|
|
|
62
|
-
@pytest.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
"river_forcing",
|
|
66
|
-
"river_forcing_for_grid_that_straddles_dateline",
|
|
67
|
-
"river_forcing_with_bgc",
|
|
68
|
-
],
|
|
69
|
-
)
|
|
70
|
-
def test_successful_initialization_with_climatological_dai_data(
|
|
71
|
-
river_forcing_fixture, request
|
|
85
|
+
@pytest.fixture
|
|
86
|
+
def river_forcing_with_prescribed_single_cell_indices(
|
|
87
|
+
single_cell_indices, iceland_test_grid
|
|
72
88
|
):
|
|
89
|
+
"""Fixture for creating a RiverForcing object based on the global Dai river dataset,
|
|
90
|
+
using manually specified single-cell river indices instead of relying on automatic
|
|
91
|
+
detection."""
|
|
73
92
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
assert "river_time" in river_forcing.ds
|
|
83
|
-
assert hasattr(
|
|
84
|
-
river_forcing.ds.river_time,
|
|
85
|
-
"cycle_length",
|
|
93
|
+
start_time = datetime(1998, 1, 1)
|
|
94
|
+
end_time = datetime(1998, 3, 1)
|
|
95
|
+
|
|
96
|
+
return RiverForcing(
|
|
97
|
+
grid=iceland_test_grid,
|
|
98
|
+
start_time=start_time,
|
|
99
|
+
end_time=end_time,
|
|
100
|
+
indices=single_cell_indices,
|
|
86
101
|
)
|
|
87
|
-
assert hasattr(river_forcing.ds, "climatology")
|
|
88
102
|
|
|
89
103
|
|
|
90
|
-
|
|
104
|
+
@pytest.fixture
|
|
105
|
+
def river_forcing_with_prescribed_multi_cell_indices(
|
|
106
|
+
multi_cell_indices, iceland_test_grid
|
|
107
|
+
):
|
|
108
|
+
"""Fixture for creating a RiverForcing object based on the global Dai river dataset,
|
|
109
|
+
using manually specified multi-cell river indices instead of relying on automatic
|
|
110
|
+
detection."""
|
|
111
|
+
|
|
112
|
+
start_time = datetime(1998, 1, 1)
|
|
113
|
+
end_time = datetime(1998, 3, 1)
|
|
91
114
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
assert not hasattr(
|
|
98
|
-
river_forcing_no_climatology.ds.river_time,
|
|
99
|
-
"cycle_length",
|
|
115
|
+
return RiverForcing(
|
|
116
|
+
grid=iceland_test_grid,
|
|
117
|
+
start_time=start_time,
|
|
118
|
+
end_time=end_time,
|
|
119
|
+
indices=multi_cell_indices,
|
|
100
120
|
)
|
|
101
|
-
assert not hasattr(river_forcing_no_climatology.ds, "climatology")
|
|
102
121
|
|
|
103
122
|
|
|
104
|
-
def
|
|
123
|
+
def compare_dictionaries(dict1, dict2):
|
|
124
|
+
assert dict1.keys() == dict2.keys()
|
|
125
|
+
|
|
126
|
+
for key in dict1.keys():
|
|
127
|
+
assert np.array_equal(dict1[key], dict2[key])
|
|
105
128
|
|
|
106
|
-
xr.testing.assert_allclose(river_forcing.ds, river_forcing_climatology.ds)
|
|
107
129
|
|
|
108
|
-
|
|
109
|
-
|
|
130
|
+
class TestRiverForcingGeneral:
|
|
131
|
+
@pytest.mark.parametrize(
|
|
132
|
+
"river_forcing_fixture",
|
|
133
|
+
[
|
|
134
|
+
"river_forcing",
|
|
135
|
+
"river_forcing_climatology",
|
|
136
|
+
"river_forcing_with_bgc",
|
|
137
|
+
"river_forcing_for_grid_that_straddles_dateline",
|
|
138
|
+
"river_forcing_with_prescribed_single_cell_indices",
|
|
139
|
+
"river_forcing_with_prescribed_multi_cell_indices",
|
|
140
|
+
],
|
|
110
141
|
)
|
|
111
|
-
|
|
112
|
-
river_forcing
|
|
142
|
+
def test_successful_initialization(self, river_forcing_fixture, request):
|
|
143
|
+
river_forcing = request.getfixturevalue(river_forcing_fixture)
|
|
144
|
+
assert isinstance(river_forcing.ds, xr.Dataset)
|
|
145
|
+
assert len(river_forcing.ds.nriver) > 0
|
|
146
|
+
assert len(river_forcing.original_indices) > 0
|
|
147
|
+
assert len(river_forcing.indices) > 0
|
|
148
|
+
assert "river_volume" in river_forcing.ds
|
|
149
|
+
assert "river_tracer" in river_forcing.ds
|
|
150
|
+
assert "river_time" in river_forcing.ds
|
|
151
|
+
|
|
152
|
+
@pytest.mark.parametrize(
|
|
153
|
+
"river_forcing_fixture",
|
|
154
|
+
[
|
|
155
|
+
"river_forcing",
|
|
156
|
+
"river_forcing_climatology",
|
|
157
|
+
"river_forcing_with_bgc",
|
|
158
|
+
"river_forcing_with_prescribed_single_cell_indices",
|
|
159
|
+
"river_forcing_with_prescribed_multi_cell_indices",
|
|
160
|
+
],
|
|
113
161
|
)
|
|
162
|
+
def test_climatology_attributes(self, river_forcing_fixture, request):
|
|
163
|
+
river_forcing = request.getfixturevalue(river_forcing_fixture)
|
|
164
|
+
assert river_forcing.climatology
|
|
165
|
+
assert hasattr(
|
|
166
|
+
river_forcing.ds.river_time,
|
|
167
|
+
"cycle_length",
|
|
168
|
+
)
|
|
169
|
+
assert hasattr(river_forcing.ds, "climatology")
|
|
114
170
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
171
|
+
def test_no_climatology_attributes(self, river_forcing_no_climatology, request):
|
|
172
|
+
assert not river_forcing_no_climatology.climatology
|
|
173
|
+
assert not hasattr(
|
|
174
|
+
river_forcing_no_climatology.ds.river_time,
|
|
175
|
+
"cycle_length",
|
|
176
|
+
)
|
|
177
|
+
assert not hasattr(river_forcing_no_climatology.ds, "climatology")
|
|
178
|
+
|
|
179
|
+
@pytest.mark.parametrize(
|
|
180
|
+
"river_forcing_fixture",
|
|
181
|
+
[
|
|
182
|
+
"river_forcing_climatology",
|
|
183
|
+
"river_forcing_no_climatology",
|
|
184
|
+
"river_forcing_with_bgc",
|
|
185
|
+
"river_forcing_with_prescribed_single_cell_indices",
|
|
186
|
+
"river_forcing_with_prescribed_multi_cell_indices",
|
|
187
|
+
],
|
|
123
188
|
)
|
|
189
|
+
def test_constant_tracers(self, river_forcing_fixture, request):
|
|
190
|
+
river_forcing = request.getfixturevalue(river_forcing_fixture)
|
|
191
|
+
np.testing.assert_allclose(
|
|
192
|
+
river_forcing.ds.river_tracer.isel(ntracers=0).values, 17.0, atol=0
|
|
193
|
+
)
|
|
194
|
+
np.testing.assert_allclose(
|
|
195
|
+
river_forcing.ds.river_tracer.isel(ntracers=1).values, 1.0, atol=0
|
|
196
|
+
)
|
|
197
|
+
np.testing.assert_allclose(
|
|
198
|
+
river_forcing.ds.river_tracer.isel(ntracers=slice(2, None)).values,
|
|
199
|
+
0.0,
|
|
200
|
+
atol=0,
|
|
201
|
+
)
|
|
124
202
|
|
|
203
|
+
def test_reproducibility_same_grid(self, river_forcing):
|
|
125
204
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"river_forcing_with_bgc",
|
|
132
|
-
],
|
|
133
|
-
)
|
|
134
|
-
def test_constant_tracers(river_forcing_fixture, request):
|
|
135
|
-
river_forcing = request.getfixturevalue(river_forcing_fixture)
|
|
205
|
+
the_same_river_forcing = RiverForcing(
|
|
206
|
+
grid=river_forcing.grid,
|
|
207
|
+
start_time=datetime(1998, 1, 1),
|
|
208
|
+
end_time=datetime(1998, 3, 1),
|
|
209
|
+
)
|
|
136
210
|
|
|
137
|
-
|
|
138
|
-
|
|
211
|
+
assert river_forcing == the_same_river_forcing
|
|
212
|
+
|
|
213
|
+
@pytest.mark.parametrize(
|
|
214
|
+
"river_forcing_fixture",
|
|
215
|
+
[
|
|
216
|
+
"river_forcing_climatology",
|
|
217
|
+
"river_forcing_no_climatology",
|
|
218
|
+
"river_forcing_with_bgc",
|
|
219
|
+
"river_forcing_with_prescribed_single_cell_indices",
|
|
220
|
+
"river_forcing_with_prescribed_multi_cell_indices",
|
|
221
|
+
],
|
|
139
222
|
)
|
|
140
|
-
|
|
141
|
-
river_forcing.
|
|
223
|
+
def test_river_locations_are_along_coast(self, river_forcing_fixture, request):
|
|
224
|
+
river_forcing = request.getfixturevalue(river_forcing_fixture)
|
|
225
|
+
|
|
226
|
+
mask = river_forcing.grid.ds.mask_rho
|
|
227
|
+
faces = (
|
|
228
|
+
mask.shift(eta_rho=1)
|
|
229
|
+
+ mask.shift(eta_rho=-1)
|
|
230
|
+
+ mask.shift(xi_rho=1)
|
|
231
|
+
+ mask.shift(xi_rho=-1)
|
|
232
|
+
)
|
|
233
|
+
coast = (1 - mask) * (faces > 0)
|
|
234
|
+
|
|
235
|
+
indices = river_forcing.indices
|
|
236
|
+
for name in indices.keys():
|
|
237
|
+
for (eta_rho, xi_rho) in indices[name]:
|
|
238
|
+
assert coast[eta_rho, xi_rho]
|
|
239
|
+
assert river_forcing.ds["river_location"][eta_rho, xi_rho] > 0
|
|
240
|
+
|
|
241
|
+
def test_missing_source_name(self, iceland_test_grid):
|
|
242
|
+
with pytest.raises(ValueError, match="`source` must include a 'name'."):
|
|
243
|
+
RiverForcing(
|
|
244
|
+
grid=iceland_test_grid,
|
|
245
|
+
start_time=datetime(1998, 1, 1),
|
|
246
|
+
end_time=datetime(1998, 3, 1),
|
|
247
|
+
source={"path": "river_data.nc"},
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
def test_river_forcing_plot(self, river_forcing_with_bgc):
|
|
251
|
+
"""Test plot method."""
|
|
252
|
+
|
|
253
|
+
river_forcing_with_bgc.plot_locations()
|
|
254
|
+
river_forcing_with_bgc.plot("river_volume")
|
|
255
|
+
river_forcing_with_bgc.plot("river_temp")
|
|
256
|
+
river_forcing_with_bgc.plot("river_salt")
|
|
257
|
+
river_forcing_with_bgc.plot("river_ALK")
|
|
258
|
+
river_forcing_with_bgc.plot("river_PO4")
|
|
259
|
+
|
|
260
|
+
@pytest.mark.parametrize(
|
|
261
|
+
"river_forcing_fixture",
|
|
262
|
+
[
|
|
263
|
+
"river_forcing_with_bgc",
|
|
264
|
+
"river_forcing_with_prescribed_multi_cell_indices",
|
|
265
|
+
],
|
|
142
266
|
)
|
|
143
|
-
|
|
144
|
-
|
|
267
|
+
def test_river_forcing_save(self, river_forcing_fixture, tmp_path, request):
|
|
268
|
+
"""Test save method."""
|
|
269
|
+
|
|
270
|
+
river_forcing = request.getfixturevalue(river_forcing_fixture)
|
|
271
|
+
for file_str in ["test_rivers", "test_rivers.nc"]:
|
|
272
|
+
# Create a temporary filepath using the tmp_path fixture
|
|
273
|
+
for filepath in [tmp_path / file_str, str(tmp_path / file_str)]:
|
|
274
|
+
|
|
275
|
+
saved_filenames = river_forcing.save(filepath)
|
|
276
|
+
# Check if the .nc file was created
|
|
277
|
+
filepath = Path(filepath).with_suffix(".nc")
|
|
278
|
+
assert saved_filenames == [filepath]
|
|
279
|
+
assert filepath.exists()
|
|
280
|
+
# Clean up the .nc file
|
|
281
|
+
filepath.unlink()
|
|
282
|
+
|
|
283
|
+
@pytest.mark.parametrize(
|
|
284
|
+
"river_forcing_fixture",
|
|
285
|
+
[
|
|
286
|
+
"river_forcing_climatology",
|
|
287
|
+
"river_forcing_no_climatology",
|
|
288
|
+
"river_forcing_with_bgc",
|
|
289
|
+
"river_forcing_with_prescribed_single_cell_indices",
|
|
290
|
+
"river_forcing_with_prescribed_multi_cell_indices",
|
|
291
|
+
],
|
|
145
292
|
)
|
|
293
|
+
def test_roundtrip_yaml(self, river_forcing_fixture, request, tmp_path, caplog):
|
|
294
|
+
"""Test that creating an RiverForcing object, saving its parameters to yaml
|
|
295
|
+
file, and re-opening yaml file creates the same object."""
|
|
146
296
|
|
|
297
|
+
river_forcing = request.getfixturevalue(river_forcing_fixture)
|
|
147
298
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
],
|
|
155
|
-
)
|
|
156
|
-
def test_river_locations_are_along_coast(river_forcing_fixture, request):
|
|
157
|
-
river_forcing = request.getfixturevalue(river_forcing_fixture)
|
|
158
|
-
|
|
159
|
-
mask = river_forcing.grid.ds.mask_rho
|
|
160
|
-
faces = (
|
|
161
|
-
mask.shift(eta_rho=1)
|
|
162
|
-
+ mask.shift(eta_rho=-1)
|
|
163
|
-
+ mask.shift(xi_rho=1)
|
|
164
|
-
+ mask.shift(xi_rho=-1)
|
|
165
|
-
)
|
|
166
|
-
coast = (1 - mask) * (faces > 0)
|
|
299
|
+
# Create a temporary filepath using the tmp_path fixture
|
|
300
|
+
file_str = "test_yaml"
|
|
301
|
+
for filepath in [
|
|
302
|
+
tmp_path / file_str,
|
|
303
|
+
str(tmp_path / file_str),
|
|
304
|
+
]: # test for Path object and str
|
|
167
305
|
|
|
168
|
-
|
|
169
|
-
for i in range(len(indices["station"])):
|
|
170
|
-
eta_rho = indices["eta_rho"][i]
|
|
171
|
-
xi_rho = indices["xi_rho"][i]
|
|
172
|
-
assert coast[eta_rho, xi_rho]
|
|
173
|
-
assert river_forcing.ds["river_location"][eta_rho, xi_rho] > 0
|
|
306
|
+
river_forcing.to_yaml(filepath)
|
|
174
307
|
|
|
308
|
+
# Clear caplog before running the test
|
|
309
|
+
caplog.clear()
|
|
175
310
|
|
|
176
|
-
|
|
311
|
+
with caplog.at_level(logging.INFO):
|
|
312
|
+
river_forcing_from_file = RiverForcing.from_yaml(filepath)
|
|
177
313
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
314
|
+
assert "Use provided river indices." in caplog.text
|
|
315
|
+
assert river_forcing == river_forcing_from_file
|
|
316
|
+
|
|
317
|
+
filepath = Path(filepath)
|
|
318
|
+
filepath.unlink()
|
|
319
|
+
|
|
320
|
+
@pytest.mark.parametrize(
|
|
321
|
+
"river_forcing_fixture",
|
|
322
|
+
[
|
|
323
|
+
"river_forcing_climatology",
|
|
324
|
+
"river_forcing_no_climatology",
|
|
325
|
+
"river_forcing_with_bgc",
|
|
326
|
+
"river_forcing_with_prescribed_single_cell_indices",
|
|
327
|
+
"river_forcing_with_prescribed_multi_cell_indices",
|
|
328
|
+
],
|
|
187
329
|
)
|
|
330
|
+
def test_files_have_same_hash(self, river_forcing_fixture, request, tmp_path):
|
|
188
331
|
|
|
189
|
-
|
|
190
|
-
RiverForcing(
|
|
191
|
-
grid=grid,
|
|
192
|
-
start_time=datetime(1998, 1, 1),
|
|
193
|
-
end_time=datetime(1998, 3, 1),
|
|
194
|
-
source={"path": "river_data.nc"},
|
|
195
|
-
)
|
|
332
|
+
river_forcing = request.getfixturevalue(river_forcing_fixture)
|
|
196
333
|
|
|
334
|
+
yaml_filepath = tmp_path / "test_yaml.yaml"
|
|
335
|
+
filepath1 = tmp_path / "test1.nc"
|
|
336
|
+
filepath2 = tmp_path / "test2.nc"
|
|
197
337
|
|
|
198
|
-
|
|
338
|
+
river_forcing.to_yaml(yaml_filepath)
|
|
339
|
+
river_forcing.save(filepath1)
|
|
340
|
+
rf_from_file = RiverForcing.from_yaml(yaml_filepath)
|
|
341
|
+
rf_from_file.save(filepath2)
|
|
199
342
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
nx=2, ny=2, size_x=50, size_y=50, center_lon=0, center_lat=55, rot=10, N=3
|
|
203
|
-
)
|
|
204
|
-
with pytest.raises(
|
|
205
|
-
ValueError,
|
|
206
|
-
match="No relevant rivers found.",
|
|
207
|
-
):
|
|
343
|
+
hash1 = calculate_file_hash(filepath1)
|
|
344
|
+
hash2 = calculate_file_hash(filepath2)
|
|
208
345
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
346
|
+
assert hash1 == hash2, f"Hashes do not match: {hash1} != {hash2}"
|
|
347
|
+
|
|
348
|
+
yaml_filepath.unlink()
|
|
349
|
+
filepath1.unlink()
|
|
350
|
+
filepath2.unlink()
|
|
351
|
+
|
|
352
|
+
def test_from_yaml_missing_river_forcing(self, tmp_path):
|
|
353
|
+
yaml_content = textwrap.dedent(
|
|
354
|
+
"""\
|
|
355
|
+
---
|
|
356
|
+
roms_tools_version: 0.0.0
|
|
357
|
+
---
|
|
358
|
+
Grid:
|
|
359
|
+
nx: 100
|
|
360
|
+
ny: 100
|
|
361
|
+
size_x: 1800
|
|
362
|
+
size_y: 2400
|
|
363
|
+
center_lon: -10
|
|
364
|
+
center_lat: 61
|
|
365
|
+
rot: -20
|
|
366
|
+
topography_source:
|
|
367
|
+
name: ETOPO5
|
|
368
|
+
hmin: 5.0
|
|
369
|
+
"""
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
# Create a temporary filepath using the tmp_path fixture
|
|
373
|
+
file_str = "test_yaml"
|
|
374
|
+
for yaml_filepath in [
|
|
375
|
+
tmp_path / file_str,
|
|
376
|
+
str(tmp_path / file_str),
|
|
377
|
+
]: # test for Path object and str
|
|
378
|
+
|
|
379
|
+
# Write YAML content to file
|
|
380
|
+
if isinstance(yaml_filepath, Path):
|
|
381
|
+
yaml_filepath.write_text(yaml_content)
|
|
382
|
+
else:
|
|
383
|
+
with open(yaml_filepath, "w") as f:
|
|
384
|
+
f.write(yaml_content)
|
|
385
|
+
|
|
386
|
+
with pytest.raises(
|
|
387
|
+
ValueError,
|
|
388
|
+
match="No RiverForcing configuration found in the YAML file.",
|
|
389
|
+
):
|
|
390
|
+
RiverForcing.from_yaml(yaml_filepath)
|
|
391
|
+
|
|
392
|
+
yaml_filepath = Path(yaml_filepath)
|
|
393
|
+
yaml_filepath.unlink()
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
class TestRiverForcingWithoutPrescribedIndices:
|
|
397
|
+
start_time = datetime(1998, 1, 1)
|
|
398
|
+
end_time = datetime(1998, 3, 1)
|
|
399
|
+
|
|
400
|
+
def test_logging_message(self, iceland_test_grid, caplog):
|
|
401
|
+
|
|
402
|
+
with caplog.at_level(logging.INFO):
|
|
403
|
+
RiverForcing(
|
|
404
|
+
grid=iceland_test_grid,
|
|
405
|
+
start_time=self.start_time,
|
|
406
|
+
end_time=self.end_time,
|
|
407
|
+
)
|
|
408
|
+
# Verify the info message in the log
|
|
409
|
+
assert "No river indices provided." in caplog.text
|
|
410
|
+
|
|
411
|
+
def test_reproducibility(self, river_forcing, river_forcing_climatology):
|
|
412
|
+
"""Verify that `river_forcing` and `river_forcing_climatology` produce identical
|
|
413
|
+
outputs.
|
|
414
|
+
|
|
415
|
+
`river_forcing` is initialized with `convert_to_climatology="if_any_missing"`, meaning
|
|
416
|
+
it fell back to climatology. This test ensures that the resulting datasets
|
|
417
|
+
and river index mappings are the same between the two cases.
|
|
418
|
+
"""
|
|
419
|
+
xr.testing.assert_allclose(river_forcing.ds, river_forcing_climatology.ds)
|
|
420
|
+
compare_dictionaries(
|
|
421
|
+
river_forcing.original_indices, river_forcing_climatology.original_indices
|
|
213
422
|
)
|
|
423
|
+
compare_dictionaries(river_forcing.indices, river_forcing_climatology.indices)
|
|
214
424
|
|
|
425
|
+
def test_no_rivers_found(self):
|
|
215
426
|
|
|
216
|
-
|
|
427
|
+
# Create a grid over open ocean
|
|
428
|
+
grid = Grid(
|
|
429
|
+
nx=2, ny=2, size_x=50, size_y=50, center_lon=0, center_lat=55, rot=10, N=3
|
|
430
|
+
)
|
|
217
431
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
start_time=datetime(1998, 1, 1),
|
|
221
|
-
end_time=datetime(1998, 3, 1),
|
|
222
|
-
)
|
|
432
|
+
with pytest.raises(ValueError, match="No relevant rivers found."):
|
|
433
|
+
RiverForcing(grid=grid, start_time=self.start_time, end_time=self.end_time)
|
|
223
434
|
|
|
224
|
-
assert river_forcing == the_same_river_forcing
|
|
225
435
|
|
|
436
|
+
class TestRiverForcingWithPrescribedIndices:
|
|
437
|
+
start_time = datetime(1998, 1, 1)
|
|
438
|
+
end_time = datetime(1998, 3, 1)
|
|
226
439
|
|
|
227
|
-
def
|
|
440
|
+
def test_logging_message(self, single_cell_indices, caplog, iceland_test_grid):
|
|
228
441
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
442
|
+
with caplog.at_level(logging.INFO):
|
|
443
|
+
RiverForcing(
|
|
444
|
+
grid=iceland_test_grid,
|
|
445
|
+
start_time=self.start_time,
|
|
446
|
+
end_time=self.end_time,
|
|
447
|
+
indices=single_cell_indices,
|
|
448
|
+
)
|
|
449
|
+
# Verify the info message in the log
|
|
450
|
+
assert "Use provided river indices." in caplog.text
|
|
235
451
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
start_time=datetime(1998, 1, 1),
|
|
239
|
-
end_time=datetime(1998, 3, 1),
|
|
240
|
-
source={"name": "DAI", "path": filepath},
|
|
452
|
+
@pytest.mark.parametrize(
|
|
453
|
+
"indices_fixture", ["single_cell_indices", "multi_cell_indices"]
|
|
241
454
|
)
|
|
455
|
+
def test_indices_stay_untouched(self, indices_fixture, request, iceland_test_grid):
|
|
456
|
+
indices = request.getfixturevalue(indices_fixture)
|
|
457
|
+
|
|
458
|
+
river_forcing = RiverForcing(
|
|
459
|
+
grid=iceland_test_grid,
|
|
460
|
+
start_time=self.start_time,
|
|
461
|
+
end_time=self.end_time,
|
|
462
|
+
indices=indices,
|
|
463
|
+
)
|
|
464
|
+
river_forcing.original_indices == indices
|
|
465
|
+
river_forcing.indices == indices
|
|
242
466
|
|
|
243
|
-
|
|
467
|
+
def test_fraction(
|
|
468
|
+
self,
|
|
469
|
+
river_forcing_with_prescribed_single_cell_indices,
|
|
470
|
+
river_forcing_with_prescribed_multi_cell_indices,
|
|
471
|
+
):
|
|
472
|
+
def list_non_zero_values(data_array):
|
|
473
|
+
non_zero_values = data_array.values
|
|
474
|
+
return non_zero_values[non_zero_values != 0].tolist()
|
|
475
|
+
|
|
476
|
+
# check that all values are integers for single cell rivers
|
|
477
|
+
non_zero_values = river_forcing_with_prescribed_single_cell_indices.ds[
|
|
478
|
+
"river_location"
|
|
479
|
+
]
|
|
480
|
+
is_integer = non_zero_values == np.floor(non_zero_values)
|
|
481
|
+
assert (is_integer).all()
|
|
482
|
+
|
|
483
|
+
# check that not all values are integers for multi cell rivers
|
|
484
|
+
non_zero_values = river_forcing_with_prescribed_multi_cell_indices.ds[
|
|
485
|
+
"river_location"
|
|
486
|
+
]
|
|
487
|
+
is_integer = non_zero_values == np.floor(non_zero_values)
|
|
488
|
+
assert not (is_integer).all()
|
|
489
|
+
|
|
490
|
+
def test_reproducibility(
|
|
491
|
+
self, river_forcing, river_forcing_with_prescribed_single_cell_indices
|
|
492
|
+
):
|
|
493
|
+
"""river_forcing_with_prescribed_single_cell_indices was created with the
|
|
494
|
+
indices that were automatically inferred for river_forcing.
|
|
495
|
+
|
|
496
|
+
Test that these two are identical.
|
|
497
|
+
"""
|
|
498
|
+
assert (
|
|
499
|
+
river_forcing.indices
|
|
500
|
+
== river_forcing_with_prescribed_single_cell_indices.indices
|
|
501
|
+
)
|
|
502
|
+
assert river_forcing.ds.identical(
|
|
503
|
+
river_forcing_with_prescribed_single_cell_indices.ds
|
|
504
|
+
)
|
|
505
|
+
assert river_forcing == river_forcing_with_prescribed_single_cell_indices
|
|
244
506
|
|
|
507
|
+
def test_reproducibility_with_flipped_dictionary_entries(
|
|
508
|
+
self, tmp_path, iceland_test_grid
|
|
509
|
+
):
|
|
510
|
+
indices = {
|
|
511
|
+
"Hvita(Olfusa)": [(8, 6)],
|
|
512
|
+
"Thjorsa": [(8, 6)],
|
|
513
|
+
"JkulsFjll": [(11, 12)],
|
|
514
|
+
"Lagarfljot": [(9, 13), (10, 13)],
|
|
515
|
+
"Bruara": [(8, 6)],
|
|
516
|
+
"Svarta": [(12, 8), (12, 9), (12, 10)],
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
flipped_indices = {
|
|
520
|
+
"Thjorsa": [(8, 6)],
|
|
521
|
+
"Hvita(Olfusa)": [(8, 6)],
|
|
522
|
+
"JkulsFjll": [(11, 12)],
|
|
523
|
+
"Svarta": [(12, 10), (12, 9), (12, 8)], # also flip order of tuples here
|
|
524
|
+
"Lagarfljot": [(9, 13), (10, 13)],
|
|
525
|
+
"Bruara": [(8, 6)],
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
river_forcing = RiverForcing(
|
|
529
|
+
grid=iceland_test_grid,
|
|
530
|
+
start_time=self.start_time,
|
|
531
|
+
end_time=self.end_time,
|
|
532
|
+
indices=indices,
|
|
533
|
+
)
|
|
245
534
|
|
|
246
|
-
|
|
247
|
-
|
|
535
|
+
river_forcing_from_flipped_indices = RiverForcing(
|
|
536
|
+
grid=iceland_test_grid,
|
|
537
|
+
start_time=self.start_time,
|
|
538
|
+
end_time=self.end_time,
|
|
539
|
+
indices=flipped_indices,
|
|
540
|
+
)
|
|
248
541
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
river_forcing_with_bgc.plot("river_salt")
|
|
253
|
-
river_forcing_with_bgc.plot("river_ALK")
|
|
254
|
-
river_forcing_with_bgc.plot("river_PO4")
|
|
542
|
+
# Create a temporary filepath using the tmp_path fixture
|
|
543
|
+
file1 = Path(tmp_path / "test1.nc")
|
|
544
|
+
file2 = Path(tmp_path / "test2.nc")
|
|
255
545
|
|
|
546
|
+
river_forcing.save(file1)
|
|
547
|
+
river_forcing_from_flipped_indices.save(file2)
|
|
256
548
|
|
|
257
|
-
|
|
258
|
-
|
|
549
|
+
hash1 = calculate_file_hash(file1)
|
|
550
|
+
hash2 = calculate_file_hash(file2)
|
|
259
551
|
|
|
260
|
-
|
|
261
|
-
# Create a temporary filepath using the tmp_path fixture
|
|
262
|
-
for filepath in [tmp_path / file_str, str(tmp_path / file_str)]:
|
|
263
|
-
|
|
264
|
-
saved_filenames = river_forcing_with_bgc.save(filepath)
|
|
265
|
-
# Check if the .nc file was created
|
|
266
|
-
filepath = Path(filepath).with_suffix(".nc")
|
|
267
|
-
assert saved_filenames == [filepath]
|
|
268
|
-
assert filepath.exists()
|
|
269
|
-
# Clean up the .nc file
|
|
270
|
-
filepath.unlink()
|
|
552
|
+
assert hash1 == hash2, f"Hashes do not match: {hash1} != {hash2}"
|
|
271
553
|
|
|
554
|
+
file1.unlink()
|
|
555
|
+
file2.unlink()
|
|
272
556
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
"river_forcing_climatology",
|
|
277
|
-
"river_forcing_no_climatology",
|
|
278
|
-
"river_forcing_with_bgc",
|
|
279
|
-
],
|
|
280
|
-
)
|
|
281
|
-
def test_roundtrip_yaml(river_forcing_fixture, request, tmp_path):
|
|
282
|
-
"""Test that creating an RiverForcing object, saving its parameters to yaml file,
|
|
283
|
-
and re-opening yaml file creates the same object."""
|
|
284
|
-
|
|
285
|
-
river_forcing = request.getfixturevalue(river_forcing_fixture)
|
|
286
|
-
|
|
287
|
-
# Create a temporary filepath using the tmp_path fixture
|
|
288
|
-
file_str = "test_yaml"
|
|
289
|
-
for filepath in [
|
|
290
|
-
tmp_path / file_str,
|
|
291
|
-
str(tmp_path / file_str),
|
|
292
|
-
]: # test for Path object and str
|
|
293
|
-
|
|
294
|
-
river_forcing.to_yaml(filepath)
|
|
295
|
-
|
|
296
|
-
river_forcing_from_file = RiverForcing.from_yaml(filepath)
|
|
297
|
-
|
|
298
|
-
assert river_forcing == river_forcing_from_file
|
|
299
|
-
|
|
300
|
-
filepath = Path(filepath)
|
|
301
|
-
filepath.unlink()
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
@pytest.mark.parametrize(
|
|
305
|
-
"river_forcing_fixture",
|
|
306
|
-
[
|
|
307
|
-
"river_forcing_climatology",
|
|
308
|
-
"river_forcing_no_climatology",
|
|
309
|
-
"river_forcing_with_bgc",
|
|
310
|
-
],
|
|
311
|
-
)
|
|
312
|
-
def test_files_have_same_hash(river_forcing_fixture, request, tmp_path):
|
|
313
|
-
|
|
314
|
-
river_forcing = request.getfixturevalue(river_forcing_fixture)
|
|
315
|
-
|
|
316
|
-
yaml_filepath = tmp_path / "test_yaml.yaml"
|
|
317
|
-
filepath1 = tmp_path / "test1.nc"
|
|
318
|
-
filepath2 = tmp_path / "test2.nc"
|
|
319
|
-
|
|
320
|
-
river_forcing.to_yaml(yaml_filepath)
|
|
321
|
-
river_forcing.save(filepath1)
|
|
322
|
-
rf_from_file = RiverForcing.from_yaml(yaml_filepath)
|
|
323
|
-
rf_from_file.save(filepath2)
|
|
324
|
-
|
|
325
|
-
hash1 = calculate_file_hash(filepath1)
|
|
326
|
-
hash2 = calculate_file_hash(filepath2)
|
|
327
|
-
|
|
328
|
-
assert hash1 == hash2, f"Hashes do not match: {hash1} != {hash2}"
|
|
329
|
-
|
|
330
|
-
yaml_filepath.unlink()
|
|
331
|
-
filepath1.unlink()
|
|
332
|
-
filepath2.unlink()
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
def test_from_yaml_missing_river_forcing(tmp_path):
|
|
336
|
-
yaml_content = textwrap.dedent(
|
|
337
|
-
"""\
|
|
338
|
-
---
|
|
339
|
-
roms_tools_version: 0.0.0
|
|
340
|
-
---
|
|
341
|
-
Grid:
|
|
342
|
-
nx: 100
|
|
343
|
-
ny: 100
|
|
344
|
-
size_x: 1800
|
|
345
|
-
size_y: 2400
|
|
346
|
-
center_lon: -10
|
|
347
|
-
center_lat: 61
|
|
348
|
-
rot: -20
|
|
349
|
-
topography_source:
|
|
350
|
-
name: ETOPO5
|
|
351
|
-
hmin: 5.0
|
|
352
|
-
"""
|
|
353
|
-
)
|
|
557
|
+
def test_invalid_indices(self, iceland_test_grid):
|
|
558
|
+
invalid_single_cell_indices = {"Hvita(Olfusa)": [(0, 6)]}
|
|
559
|
+
invalid_multi_cell_indices = {"Hvita(Olfusa)": [(8, 6), (0, 6)]}
|
|
354
560
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
561
|
+
for indices in [invalid_single_cell_indices, invalid_multi_cell_indices]:
|
|
562
|
+
with pytest.raises(
|
|
563
|
+
ValueError, match="is not located on the coast at grid cell"
|
|
564
|
+
):
|
|
565
|
+
RiverForcing(
|
|
566
|
+
grid=iceland_test_grid,
|
|
567
|
+
start_time=self.start_time,
|
|
568
|
+
end_time=self.end_time,
|
|
569
|
+
indices=indices,
|
|
570
|
+
)
|
|
361
571
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
yaml_filepath.write_text(yaml_content)
|
|
365
|
-
else:
|
|
366
|
-
with open(yaml_filepath, "w") as f:
|
|
367
|
-
f.write(yaml_content)
|
|
572
|
+
def test_raise_missing_rivers(self, iceland_test_grid):
|
|
573
|
+
fake_indices = {"Hvita(Olfusa)": [(8, 6)], "fake": [(11, 12)]}
|
|
368
574
|
|
|
575
|
+
with pytest.raises(
|
|
576
|
+
ValueError, match="The following rivers were not found in the dataset"
|
|
577
|
+
):
|
|
578
|
+
RiverForcing(
|
|
579
|
+
grid=iceland_test_grid,
|
|
580
|
+
start_time=self.start_time,
|
|
581
|
+
end_time=self.end_time,
|
|
582
|
+
indices=fake_indices,
|
|
583
|
+
)
|
|
584
|
+
|
|
585
|
+
def test_indices_is_dict(self, iceland_test_grid):
|
|
586
|
+
with pytest.raises(ValueError, match="`indices` must be a dictionary."):
|
|
587
|
+
RiverForcing(
|
|
588
|
+
grid=iceland_test_grid,
|
|
589
|
+
start_time=self.start_time,
|
|
590
|
+
end_time=self.end_time,
|
|
591
|
+
indices="invalid",
|
|
592
|
+
)
|
|
593
|
+
|
|
594
|
+
def test_indices_empty(self, iceland_test_grid):
|
|
369
595
|
with pytest.raises(
|
|
370
596
|
ValueError,
|
|
371
|
-
match="
|
|
597
|
+
match="The provided 'indices' dictionary must contain at least one river.",
|
|
372
598
|
):
|
|
373
|
-
RiverForcing
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
599
|
+
RiverForcing(
|
|
600
|
+
grid=iceland_test_grid,
|
|
601
|
+
start_time=self.start_time,
|
|
602
|
+
end_time=self.end_time,
|
|
603
|
+
indices={},
|
|
604
|
+
)
|
|
605
|
+
|
|
606
|
+
def test_invalid_river_name_type(self, iceland_test_grid):
|
|
607
|
+
indices = {123: [(8, 6)]} # Invalid river name (should be a string)
|
|
608
|
+
with pytest.raises(ValueError, match="River name `123` must be a string."):
|
|
609
|
+
RiverForcing(
|
|
610
|
+
grid=iceland_test_grid,
|
|
611
|
+
start_time=self.start_time,
|
|
612
|
+
end_time=self.end_time,
|
|
613
|
+
indices=indices,
|
|
614
|
+
)
|
|
615
|
+
|
|
616
|
+
def test_invalid_river_data_type(self, iceland_test_grid):
|
|
617
|
+
indices = {
|
|
618
|
+
"Hvita(Olfusa)": "8, 6" # Invalid river data (should be a list of tuples)
|
|
619
|
+
}
|
|
620
|
+
with pytest.raises(ValueError, match="must be a list of tuples."):
|
|
621
|
+
RiverForcing(
|
|
622
|
+
grid=iceland_test_grid,
|
|
623
|
+
start_time=self.start_time,
|
|
624
|
+
end_time=self.end_time,
|
|
625
|
+
indices=indices,
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
def test_invalid_tuple_length(self, iceland_test_grid):
|
|
629
|
+
indices = {
|
|
630
|
+
"Hvita(Olfusa)": [(8, 6, 7)] # Invalid tuple length (should be length 2)
|
|
631
|
+
}
|
|
632
|
+
with pytest.raises(ValueError, match="must be a tuple of length 2"):
|
|
633
|
+
RiverForcing(
|
|
634
|
+
grid=iceland_test_grid,
|
|
635
|
+
start_time=self.start_time,
|
|
636
|
+
end_time=self.end_time,
|
|
637
|
+
indices=indices,
|
|
638
|
+
)
|
|
639
|
+
|
|
640
|
+
def test_invalid_eta_rho_type(self, iceland_test_grid):
|
|
641
|
+
indices = {
|
|
642
|
+
"Hvita(Olfusa)": [("a", 6)] # Invalid eta_rho (should be an integer)
|
|
643
|
+
}
|
|
644
|
+
with pytest.raises(ValueError, match="First element of tuple for river"):
|
|
645
|
+
RiverForcing(
|
|
646
|
+
grid=iceland_test_grid,
|
|
647
|
+
start_time=self.start_time,
|
|
648
|
+
end_time=self.end_time,
|
|
649
|
+
indices=indices,
|
|
650
|
+
)
|
|
651
|
+
|
|
652
|
+
def test_invalid_xi_rho_type(self, iceland_test_grid):
|
|
653
|
+
indices = {"Hvita(Olfusa)": [(8, "b")]} # Invalid xi_rho (should be an integer)
|
|
654
|
+
with pytest.raises(ValueError, match="Second element of tuple for river"):
|
|
655
|
+
RiverForcing(
|
|
656
|
+
grid=iceland_test_grid,
|
|
657
|
+
start_time=self.start_time,
|
|
658
|
+
end_time=self.end_time,
|
|
659
|
+
indices=indices,
|
|
660
|
+
)
|
|
661
|
+
|
|
662
|
+
def test_eta_rho_out_of_range(self, iceland_test_grid):
|
|
663
|
+
indices = {"Hvita(Olfusa)": [(20, 6)]} # eta_rho out of valid range [0, 17]
|
|
664
|
+
with pytest.raises(ValueError, match="Value of eta_rho for river"):
|
|
665
|
+
RiverForcing(
|
|
666
|
+
grid=iceland_test_grid,
|
|
667
|
+
start_time=self.start_time,
|
|
668
|
+
end_time=self.end_time,
|
|
669
|
+
indices=indices,
|
|
670
|
+
)
|
|
671
|
+
|
|
672
|
+
def test_xi_rho_out_of_range(self, iceland_test_grid):
|
|
673
|
+
indices = {"Hvita(Olfusa)": [(8, 20)]} # xi_rho out of valid range [0, 17]
|
|
674
|
+
with pytest.raises(ValueError, match="Value of xi_rho for river"):
|
|
675
|
+
RiverForcing(
|
|
676
|
+
grid=iceland_test_grid,
|
|
677
|
+
start_time=self.start_time,
|
|
678
|
+
end_time=self.end_time,
|
|
679
|
+
indices=indices,
|
|
680
|
+
)
|
|
681
|
+
|
|
682
|
+
def test_duplicate_location(self, iceland_test_grid):
|
|
683
|
+
indices = {"Hvita(Olfusa)": [(8, 6), (8, 6)]} # Duplicate location
|
|
684
|
+
with pytest.raises(ValueError, match="Duplicate location"):
|
|
685
|
+
RiverForcing(
|
|
686
|
+
grid=iceland_test_grid,
|
|
687
|
+
start_time=self.start_time,
|
|
688
|
+
end_time=self.end_time,
|
|
689
|
+
indices=indices,
|
|
690
|
+
)
|