roms-tools 3.1.2__py3-none-any.whl → 3.3.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.
- roms_tools/__init__.py +3 -0
- roms_tools/analysis/cdr_analysis.py +203 -0
- roms_tools/analysis/cdr_ensemble.py +198 -0
- roms_tools/analysis/roms_output.py +80 -46
- roms_tools/data/grids/GLORYS_global_grid.nc +0 -0
- roms_tools/download.py +4 -0
- roms_tools/plot.py +113 -51
- roms_tools/setup/boundary_forcing.py +45 -20
- roms_tools/setup/cdr_forcing.py +122 -8
- roms_tools/setup/cdr_release.py +161 -8
- roms_tools/setup/grid.py +150 -141
- roms_tools/setup/initial_conditions.py +113 -48
- roms_tools/setup/{datasets.py → lat_lon_datasets.py} +443 -938
- roms_tools/setup/mask.py +63 -7
- roms_tools/setup/nesting.py +314 -117
- roms_tools/setup/river_datasets.py +527 -0
- roms_tools/setup/river_forcing.py +46 -20
- roms_tools/setup/surface_forcing.py +7 -9
- roms_tools/setup/tides.py +2 -3
- roms_tools/setup/topography.py +8 -10
- roms_tools/setup/utils.py +396 -23
- roms_tools/tests/test_analysis/test_cdr_analysis.py +144 -0
- roms_tools/tests/test_analysis/test_cdr_ensemble.py +202 -0
- roms_tools/tests/test_analysis/test_roms_output.py +61 -3
- roms_tools/tests/test_setup/test_boundary_forcing.py +54 -52
- roms_tools/tests/test_setup/test_cdr_forcing.py +54 -0
- roms_tools/tests/test_setup/test_cdr_release.py +118 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zarr.json +406 -406
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_south/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_north/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_south/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zarr.json +182 -182
- roms_tools/tests/test_setup/test_data/grid.zarr/h/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/grid.zarr/zarr.json +191 -191
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/h/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/zarr.json +210 -210
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK_ALT_CO2/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC_ALT_CO2/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOCr/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DON/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DONr/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOP/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOPr/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Fe/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Lig/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NH4/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NO3/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/O2/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/PO4/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/SiO3/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatChl/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatFe/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatP/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatSi/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazChl/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazFe/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazP/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/salt/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spCaCO3/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spChl/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spFe/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spP/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/temp/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/u/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ubar/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/v/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/vbar/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zarr.json +182 -182
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zooC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/salt/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/temp/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/u/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ubar/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/v/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/vbar/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/zarr.json +187 -187
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Im/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Re/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Im/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Re/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/zarr.json +66 -66
- roms_tools/tests/test_setup/test_grid.py +236 -115
- roms_tools/tests/test_setup/test_initial_conditions.py +94 -41
- roms_tools/tests/test_setup/{test_datasets.py → test_lat_lon_datasets.py} +409 -100
- roms_tools/tests/test_setup/test_nesting.py +119 -31
- roms_tools/tests/test_setup/test_river_datasets.py +48 -0
- roms_tools/tests/test_setup/test_surface_forcing.py +2 -1
- roms_tools/tests/test_setup/test_utils.py +92 -2
- roms_tools/tests/test_setup/utils.py +71 -0
- roms_tools/tests/test_tiling/test_join.py +241 -0
- roms_tools/tests/test_utils.py +139 -17
- roms_tools/tiling/join.py +189 -0
- roms_tools/utils.py +131 -99
- {roms_tools-3.1.2.dist-info → roms_tools-3.3.0.dist-info}/METADATA +12 -2
- {roms_tools-3.1.2.dist-info → roms_tools-3.3.0.dist-info}/RECORD +221 -211
- {roms_tools-3.1.2.dist-info → roms_tools-3.3.0.dist-info}/WHEEL +0 -0
- {roms_tools-3.1.2.dist-info → roms_tools-3.3.0.dist-info}/licenses/LICENSE +0 -0
- {roms_tools-3.1.2.dist-info → roms_tools-3.3.0.dist-info}/top_level.txt +0 -0
roms_tools/setup/nesting.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from collections.abc import Callable
|
|
2
3
|
from dataclasses import dataclass, field
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import Any
|
|
@@ -9,8 +10,9 @@ from scipy.interpolate import griddata, interp1d
|
|
|
9
10
|
|
|
10
11
|
from roms_tools import Grid
|
|
11
12
|
from roms_tools.plot import plot_nesting
|
|
12
|
-
from roms_tools.setup.topography import
|
|
13
|
+
from roms_tools.setup.topography import clip_depth
|
|
13
14
|
from roms_tools.setup.utils import (
|
|
15
|
+
Timed,
|
|
14
16
|
from_yaml,
|
|
15
17
|
get_boundary_coords,
|
|
16
18
|
interpolate_from_rho_to_u,
|
|
@@ -48,6 +50,8 @@ class ChildGrid(Grid):
|
|
|
48
50
|
|
|
49
51
|
- `"prefix"` (str): Prefix for variable names in `ds_nesting`. Defaults to `"child"`.
|
|
50
52
|
- `"period"` (float): Temporal resolution for boundary outputs in seconds. Defaults to 3600 (hourly).
|
|
53
|
+
verbose: bool, optional
|
|
54
|
+
Indicates whether to print grid generation steps with timing. Defaults to False.
|
|
51
55
|
"""
|
|
52
56
|
|
|
53
57
|
parent_grid: Grid
|
|
@@ -67,6 +71,8 @@ class ChildGrid(Grid):
|
|
|
67
71
|
default_factory=lambda: {"prefix": "child", "period": 3600.0}
|
|
68
72
|
)
|
|
69
73
|
"""Dictionary configuring the boundary nesting process."""
|
|
74
|
+
verbose: bool = False
|
|
75
|
+
"""Whether to print grid generation steps with timing."""
|
|
70
76
|
|
|
71
77
|
ds: xr.Dataset = field(init=False, repr=False)
|
|
72
78
|
"""An xarray Dataset containing child grid variables aligned with the
|
|
@@ -75,87 +81,144 @@ class ChildGrid(Grid):
|
|
|
75
81
|
"""An xarray Dataset containing boundary mappings, where child grid boundaries are
|
|
76
82
|
mapped onto parent grid indices."""
|
|
77
83
|
|
|
78
|
-
def
|
|
79
|
-
super().__post_init__()
|
|
80
|
-
self._map_child_boundaries_onto_parent_grid_indices()
|
|
81
|
-
self._modify_child_topography_and_mask()
|
|
82
|
-
|
|
83
|
-
def _map_child_boundaries_onto_parent_grid_indices(self):
|
|
84
|
+
def _map_child_boundaries_onto_parent_grid_indices(self, verbose: bool = False):
|
|
84
85
|
"""Maps child grid boundary points onto absolute indices of the parent grid."""
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
parent_grid_ds,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
86
|
+
with Timed(
|
|
87
|
+
"=== Mapping the child grid boundary points onto the indices of the parent grid ===",
|
|
88
|
+
verbose=verbose,
|
|
89
|
+
):
|
|
90
|
+
# Prepare parent and child grid datasets by adjusting longitudes for dateline crossing
|
|
91
|
+
parent_grid_ds, child_grid_ds = self._prepare_grid_datasets()
|
|
92
|
+
|
|
93
|
+
# Map child boundaries onto parent grid indices
|
|
94
|
+
ds_nesting = map_child_boundaries_onto_parent_grid_indices(
|
|
95
|
+
parent_grid_ds,
|
|
96
|
+
child_grid_ds,
|
|
97
|
+
self.boundaries,
|
|
98
|
+
self.metadata["prefix"],
|
|
99
|
+
self.metadata["period"],
|
|
100
|
+
)
|
|
96
101
|
|
|
97
|
-
|
|
102
|
+
self.ds_nesting = ds_nesting
|
|
98
103
|
|
|
99
|
-
def
|
|
100
|
-
|
|
104
|
+
def _apply_child_modification(
|
|
105
|
+
self,
|
|
106
|
+
modifier: Callable,
|
|
107
|
+
modifier_name: str,
|
|
108
|
+
verbose: bool = False,
|
|
109
|
+
):
|
|
110
|
+
"""Shared logic for modifying child mask/topography."""
|
|
111
|
+
with Timed(f"=== Modifying the child {modifier_name} ===", verbose=verbose):
|
|
112
|
+
# Prepare datasets (fix dateline)
|
|
113
|
+
parent_grid_ds, child_grid_ds = self._prepare_grid_datasets()
|
|
114
|
+
|
|
115
|
+
# Apply modification function
|
|
116
|
+
child_grid_ds = modifier(parent_grid_ds, child_grid_ds)
|
|
117
|
+
|
|
118
|
+
# Restore longitudes to 0-360
|
|
119
|
+
_, child_grid_ds = self._finalize_grid_datasets(
|
|
120
|
+
parent_grid_ds, child_grid_ds
|
|
121
|
+
)
|
|
101
122
|
|
|
102
|
-
|
|
103
|
-
minimum.
|
|
104
|
-
"""
|
|
105
|
-
# Prepare parent and child grid datasets by adjusting longitudes for dateline crossing
|
|
106
|
-
parent_grid_ds, child_grid_ds = self._prepare_grid_datasets()
|
|
123
|
+
self.ds = child_grid_ds
|
|
107
124
|
|
|
108
|
-
|
|
109
|
-
|
|
125
|
+
def _modify_child_mask(self, verbose: bool = False) -> None:
|
|
126
|
+
"""Adjust child grid mask to align with the parent grid."""
|
|
127
|
+
self._apply_child_modification(
|
|
128
|
+
modifier=lambda p, c: modify_child_mask(p, c, self.boundaries),
|
|
129
|
+
modifier_name="mask",
|
|
130
|
+
verbose=verbose,
|
|
110
131
|
)
|
|
111
132
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
133
|
+
def _modify_child_topography(self, hmin: float, verbose: bool = False) -> None:
|
|
134
|
+
"""Adjust child grid topography to align with the parent grid."""
|
|
135
|
+
self._apply_child_modification(
|
|
136
|
+
modifier=lambda p, c: modify_child_topography(p, c, self.boundaries, hmin),
|
|
137
|
+
modifier_name="topography",
|
|
138
|
+
verbose=verbose,
|
|
115
139
|
)
|
|
116
140
|
|
|
117
|
-
|
|
141
|
+
def update_mask(
|
|
142
|
+
self, mask_shapefile: str | Path | None = None, verbose: bool = False
|
|
143
|
+
) -> None:
|
|
144
|
+
"""
|
|
145
|
+
Update the child grid mask and ensure consistency with the parent grid.
|
|
146
|
+
|
|
147
|
+
This method performs the following steps:
|
|
148
|
+
|
|
149
|
+
1. Derives the child mask from the provided ``mask_shapefile`` (or from the
|
|
150
|
+
default Natural Earth 10m coastline if ``None``).
|
|
151
|
+
2. Updates the mapping of child boundaries to parent-grid indices.
|
|
152
|
+
This mapping depends on the updated mask, since masked (land) points may
|
|
153
|
+
extend outside the parent grid.
|
|
154
|
+
3. Adjusts the child mask to ensure consistency with the parent mask.
|
|
155
|
+
|
|
156
|
+
Parameters
|
|
157
|
+
----------
|
|
158
|
+
mask_shapefile : str or Path, optional
|
|
159
|
+
Path to a coastal shapefile used to derive the land mask. If ``None``,
|
|
160
|
+
a default coastline dataset is used.
|
|
161
|
+
verbose : bool, default False
|
|
162
|
+
If True, prints timing and progress information.
|
|
163
|
+
|
|
164
|
+
Returns
|
|
165
|
+
-------
|
|
166
|
+
None
|
|
167
|
+
Updates the internal datasets (``self.ds`` and ``self.ds_nesting``) in place,
|
|
168
|
+
modifying the mask and ensuring consistent parent-child boundary mapping.
|
|
169
|
+
"""
|
|
170
|
+
super().update_mask(mask_shapefile=mask_shapefile, verbose=verbose)
|
|
171
|
+
self._map_child_boundaries_onto_parent_grid_indices(verbose=verbose)
|
|
172
|
+
self._modify_child_mask(verbose=verbose)
|
|
118
173
|
|
|
119
174
|
def update_topography(
|
|
120
|
-
self,
|
|
175
|
+
self,
|
|
176
|
+
topography_source: dict | None = None,
|
|
177
|
+
hmin: float | None = None,
|
|
178
|
+
verbose: bool = False,
|
|
121
179
|
) -> None:
|
|
122
|
-
"""
|
|
180
|
+
"""
|
|
181
|
+
Update the child grid topography and ensure consistency with the parent grid.
|
|
182
|
+
|
|
183
|
+
This method performs the following operations:
|
|
123
184
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
185
|
+
1. Regrids the topography from the specified source.
|
|
186
|
+
2. Applies domain-wide and local smoothing.
|
|
187
|
+
3. Enforces the minimum depth constraint ``hmin``.
|
|
188
|
+
4. Adjusts the child grid topography to maintain consistency with the
|
|
189
|
+
parent grid.
|
|
190
|
+
5. Updates the internal dataset (``self.ds``) with the processed bathymetry.
|
|
129
191
|
|
|
130
192
|
Parameters
|
|
131
193
|
----------
|
|
132
194
|
topography_source : dict, optional
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
-
|
|
195
|
+
Dictionary describing the topography data source. Expected keys:
|
|
196
|
+
|
|
197
|
+
- ``"name"`` (str): Name of the source dataset (e.g., ``"SRTM15"``).
|
|
198
|
+
- ``"path"`` (str or Path): Path to the dataset file.
|
|
136
199
|
|
|
137
|
-
If
|
|
200
|
+
If ``None``, the previously configured topography source is used.
|
|
138
201
|
|
|
139
202
|
hmin : float, optional
|
|
140
|
-
|
|
141
|
-
|
|
203
|
+
Minimum allowable ocean depth (meters). If ``None``, the existing value
|
|
204
|
+
is retained.
|
|
142
205
|
|
|
143
|
-
verbose : bool,
|
|
144
|
-
If
|
|
145
|
-
timing and modifications. Defaults to `False`.
|
|
206
|
+
verbose : bool, default False
|
|
207
|
+
If ``True``, prints progress messages and timing information.
|
|
146
208
|
|
|
147
209
|
Returns
|
|
148
210
|
-------
|
|
149
211
|
None
|
|
150
|
-
|
|
151
|
-
|
|
212
|
+
Updates ``self.ds`` in place by modifying the topography field. Nothing
|
|
213
|
+
is returned.
|
|
152
214
|
"""
|
|
215
|
+
hmin = hmin or self.hmin
|
|
153
216
|
super().update_topography(
|
|
154
|
-
topography_source=topography_source,
|
|
217
|
+
topography_source=topography_source,
|
|
218
|
+
hmin=hmin,
|
|
219
|
+
verbose=verbose,
|
|
155
220
|
)
|
|
156
|
-
|
|
157
|
-
# Modify child topography and mask to match the parent grid
|
|
158
|
-
self._modify_child_topography_and_mask()
|
|
221
|
+
self._modify_child_topography(hmin=hmin, verbose=verbose)
|
|
159
222
|
|
|
160
223
|
def plot_nesting(self, with_dim_names=False) -> None:
|
|
161
224
|
"""Plot the parent and child grids in a single figure.
|
|
@@ -216,13 +279,19 @@ class ChildGrid(Grid):
|
|
|
216
279
|
write_to_yaml(forcing_dict, filepath)
|
|
217
280
|
|
|
218
281
|
@classmethod
|
|
219
|
-
def from_yaml(
|
|
282
|
+
def from_yaml(
|
|
283
|
+
cls, filepath: str | Path, verbose: bool = False, **kwargs: Any
|
|
284
|
+
) -> "ChildGrid":
|
|
220
285
|
"""Create an instance of the ChildGrid class from a YAML file.
|
|
221
286
|
|
|
222
287
|
Parameters
|
|
223
288
|
----------
|
|
224
289
|
filepath : Union[str, Path]
|
|
225
290
|
The path to the YAML file from which the parameters will be read.
|
|
291
|
+
verbose : bool, optional
|
|
292
|
+
Indicates whether to print grid generation steps with timing. Defaults to False.
|
|
293
|
+
**kwargs : Any
|
|
294
|
+
Additional keyword arguments passed to Grid.from_yaml.
|
|
226
295
|
|
|
227
296
|
Returns
|
|
228
297
|
-------
|
|
@@ -231,10 +300,12 @@ class ChildGrid(Grid):
|
|
|
231
300
|
"""
|
|
232
301
|
filepath = Path(filepath)
|
|
233
302
|
|
|
234
|
-
parent_grid = Grid.from_yaml(
|
|
303
|
+
parent_grid = Grid.from_yaml(
|
|
304
|
+
filepath, verbose=verbose, section_name="ParentGrid"
|
|
305
|
+
)
|
|
235
306
|
params = from_yaml(cls, filepath)
|
|
236
307
|
|
|
237
|
-
return cls(parent_grid=parent_grid, **params)
|
|
308
|
+
return cls(parent_grid=parent_grid, **params, verbose=verbose)
|
|
238
309
|
|
|
239
310
|
def _prepare_grid_datasets(self) -> tuple[xr.Dataset, xr.Dataset]:
|
|
240
311
|
"""Prepare parent and child grid datasets by adjusting longitudes for dateline
|
|
@@ -251,14 +322,17 @@ class ChildGrid(Grid):
|
|
|
251
322
|
- The modified child grid dataset.
|
|
252
323
|
"""
|
|
253
324
|
parent_grid_ds = wrap_longitudes(
|
|
254
|
-
self.parent_grid.ds, straddle=self.parent_grid.straddle
|
|
325
|
+
self.parent_grid.ds.copy(), straddle=self.parent_grid.straddle
|
|
255
326
|
)
|
|
256
|
-
child_grid_ds = wrap_longitudes(
|
|
327
|
+
child_grid_ds = wrap_longitudes(
|
|
328
|
+
self.ds.copy(), straddle=self.parent_grid.straddle
|
|
329
|
+
)
|
|
330
|
+
|
|
257
331
|
return parent_grid_ds, child_grid_ds
|
|
258
332
|
|
|
259
333
|
def _finalize_grid_datasets(
|
|
260
334
|
self, parent_grid_ds: xr.Dataset, child_grid_ds: xr.Dataset
|
|
261
|
-
) ->
|
|
335
|
+
) -> tuple[xr.Dataset, xr.Dataset]:
|
|
262
336
|
"""Finalize the grid datasets by converting longitudes back to the [0, 360]
|
|
263
337
|
range.
|
|
264
338
|
|
|
@@ -269,13 +343,28 @@ class ChildGrid(Grid):
|
|
|
269
343
|
|
|
270
344
|
child_grid_ds : xr.Dataset
|
|
271
345
|
The child grid dataset after modifications.
|
|
346
|
+
|
|
347
|
+
Returns
|
|
348
|
+
-------
|
|
349
|
+
tuple[xr.Dataset, xr.Dataset]
|
|
350
|
+
The finalized parent and child grid datasets with longitudes wrapped to [0, 360].
|
|
351
|
+
|
|
272
352
|
"""
|
|
273
353
|
parent_grid_ds = wrap_longitudes(parent_grid_ds, straddle=False)
|
|
274
354
|
child_grid_ds = wrap_longitudes(child_grid_ds, straddle=False)
|
|
355
|
+
|
|
275
356
|
return parent_grid_ds, child_grid_ds
|
|
276
357
|
|
|
277
358
|
@classmethod
|
|
278
|
-
def from_file(
|
|
359
|
+
def from_file(
|
|
360
|
+
cls,
|
|
361
|
+
filepath: str | Path,
|
|
362
|
+
theta_s: float | None = None,
|
|
363
|
+
theta_b: float | None = None,
|
|
364
|
+
hc: float | None = None,
|
|
365
|
+
N: int | None = None,
|
|
366
|
+
verbose: bool = False,
|
|
367
|
+
) -> "ChildGrid":
|
|
279
368
|
"""This method is disabled in this subclass.
|
|
280
369
|
|
|
281
370
|
.. noindex::
|
|
@@ -286,12 +375,12 @@ class ChildGrid(Grid):
|
|
|
286
375
|
|
|
287
376
|
|
|
288
377
|
def map_child_boundaries_onto_parent_grid_indices(
|
|
289
|
-
parent_grid_ds,
|
|
290
|
-
child_grid_ds,
|
|
291
|
-
boundaries={"south": True, "east": True, "north": True, "west": True},
|
|
292
|
-
prefix="child",
|
|
293
|
-
period=3600.0,
|
|
294
|
-
update_land_indices=True,
|
|
378
|
+
parent_grid_ds: xr.Dataset,
|
|
379
|
+
child_grid_ds: xr.Dataset,
|
|
380
|
+
boundaries: dict = {"south": True, "east": True, "north": True, "west": True},
|
|
381
|
+
prefix: str = "child",
|
|
382
|
+
period: float = 3600.0,
|
|
383
|
+
update_land_indices: bool = True,
|
|
295
384
|
):
|
|
296
385
|
"""Maps child grid boundary points onto absolute indices of the parent grid.
|
|
297
386
|
|
|
@@ -337,6 +426,7 @@ def map_child_boundaries_onto_parent_grid_indices(
|
|
|
337
426
|
bdry_coords_dict = get_boundary_coords()
|
|
338
427
|
|
|
339
428
|
# add angles at u- and v-points
|
|
429
|
+
|
|
340
430
|
child_grid_ds["angle_u"] = interpolate_from_rho_to_u(child_grid_ds["angle"])
|
|
341
431
|
child_grid_ds["angle_v"] = interpolate_from_rho_to_v(child_grid_ds["angle"])
|
|
342
432
|
|
|
@@ -367,10 +457,10 @@ def map_child_boundaries_onto_parent_grid_indices(
|
|
|
367
457
|
mask_child = child_grid_ds[names["mask"]].isel(**bdry_coords[direction])
|
|
368
458
|
|
|
369
459
|
i_eta, i_xi = interpolate_indices(
|
|
370
|
-
parent_grid_ds, lon_child, lat_child, mask_child
|
|
460
|
+
parent_grid_ds, lon_child, lat_child, mask_child, direction
|
|
371
461
|
)
|
|
372
462
|
|
|
373
|
-
if update_land_indices:
|
|
463
|
+
if update_land_indices and mask_child.sum() > 0:
|
|
374
464
|
i_eta, i_xi = update_indices_if_on_parent_land(
|
|
375
465
|
i_eta, i_xi, grid_location, parent_grid_ds
|
|
376
466
|
)
|
|
@@ -410,18 +500,25 @@ def map_child_boundaries_onto_parent_grid_indices(
|
|
|
410
500
|
}
|
|
411
501
|
ds = ds.rename(dims_to_rename)
|
|
412
502
|
|
|
413
|
-
ds = ds.assign_coords(
|
|
414
|
-
{
|
|
415
|
-
"indices_rho": ("two", ["xi", "eta"]),
|
|
416
|
-
"indices_vel": ("three", ["xi", "eta", "angle"]),
|
|
417
|
-
}
|
|
418
|
-
)
|
|
419
|
-
|
|
420
503
|
return ds
|
|
421
504
|
|
|
422
505
|
|
|
423
|
-
def interpolate_indices(
|
|
424
|
-
|
|
506
|
+
def interpolate_indices(
|
|
507
|
+
parent_grid_ds: xr.Dataset,
|
|
508
|
+
lon: xr.DataArray,
|
|
509
|
+
lat: xr.DataArray,
|
|
510
|
+
mask: xr.DataArray,
|
|
511
|
+
direction: str,
|
|
512
|
+
) -> tuple[xr.DataArray, xr.DataArray]:
|
|
513
|
+
"""Interpolate the parent indices to the child grid boundary.
|
|
514
|
+
|
|
515
|
+
Uses the parent grid ``lon_rho``/``lat_rho`` coordinates to compute
|
|
516
|
+
fractional i/j indices at child-boundary longitude/latitude points using
|
|
517
|
+
linear interpolation. The function verifies that all ocean child points
|
|
518
|
+
(based on ``mask``) lie within the parent grid and warns if child
|
|
519
|
+
boundary points fall near the parent-grid edges. Land child points that fall
|
|
520
|
+
outside the parent grid (i.e., interpolation returns NaN) are filled with
|
|
521
|
+
``-1e5``.
|
|
425
522
|
|
|
426
523
|
Parameters
|
|
427
524
|
----------
|
|
@@ -433,6 +530,9 @@ def interpolate_indices(parent_grid_ds, lon, lat, mask):
|
|
|
433
530
|
Latitudes of the child grid where interpolation is desired.
|
|
434
531
|
mask: xarray.DataArray
|
|
435
532
|
Mask for the child longitudes and latitudes under consideration.
|
|
533
|
+
direction : str
|
|
534
|
+
Boundary identifier (``"south"``, ``"north"``, ``"east"``, ``"west"``).
|
|
535
|
+
Used for generating informative warnings or errors.
|
|
436
536
|
Returns
|
|
437
537
|
-------
|
|
438
538
|
i : xarray.DataArray
|
|
@@ -467,27 +567,67 @@ def interpolate_indices(parent_grid_ds, lon, lat, mask):
|
|
|
467
567
|
i = xr.DataArray(i, dims=lon.dims)
|
|
468
568
|
j = xr.DataArray(j, dims=lon.dims)
|
|
469
569
|
|
|
470
|
-
# Check
|
|
471
|
-
if
|
|
570
|
+
# Check whether ocean child points fall outside the parent grid
|
|
571
|
+
if (
|
|
572
|
+
i.where(mask, other=0.0).isnull().any()
|
|
573
|
+
or j.where(mask, other=0.0).isnull().any()
|
|
574
|
+
):
|
|
472
575
|
raise ValueError(
|
|
473
|
-
"Some points
|
|
576
|
+
f"Some wet points on the {direction}ern boundary of the child grid lie "
|
|
577
|
+
"outside the parent grid. Please use a larger parent grid or a smaller child grid."
|
|
474
578
|
)
|
|
475
579
|
|
|
476
|
-
#
|
|
580
|
+
# Try to fix NaNs if there only a few per boundary. Fix with out-of-bounds points is not valid.
|
|
477
581
|
nxp, nyp = lon_parent.shape
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
582
|
+
nan_idx = (
|
|
583
|
+
i.isnull() | j.isnull() | (i > nxp - 2) | (i < 0) | (j > nyp - 2) | (j < 0)
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
idx = xr.DataArray(np.arange(i.size), dims=i.dims)
|
|
587
|
+
|
|
588
|
+
# Interpolate indices for points that are invalid (NaN or out-of-bounds)
|
|
589
|
+
if nan_idx.any() and not nan_idx.all():
|
|
590
|
+
idx_tmp = idx.where(~nan_idx, drop=True) # valid poins
|
|
591
|
+
i_tmp = i.where(~nan_idx, drop=True) # valid points
|
|
592
|
+
j_tmp = j.where(~nan_idx, drop=True) # valid points
|
|
593
|
+
|
|
594
|
+
interp_i = interp1d(
|
|
595
|
+
idx_tmp.values, i_tmp.values, kind="nearest", fill_value="extrapolate"
|
|
596
|
+
)
|
|
597
|
+
interp_j = interp1d(
|
|
598
|
+
idx_tmp.values, j_tmp.values, kind="nearest", fill_value="extrapolate"
|
|
599
|
+
)
|
|
600
|
+
|
|
601
|
+
i[nan_idx.values] = interp_i(idx[nan_idx].values)
|
|
602
|
+
j[nan_idx.values] = interp_j(idx[nan_idx].values)
|
|
603
|
+
|
|
604
|
+
# This should only occur in rare edge cases
|
|
605
|
+
if i.isnull().any() or j.isnull().any():
|
|
606
|
+
raise ValueError(
|
|
607
|
+
f"Mapping failed: the {direction}ern boundary of the child grid could not be "
|
|
608
|
+
"mapped onto parent-grid indices. Please adjust the parent/child grid configuration."
|
|
481
609
|
)
|
|
482
|
-
|
|
610
|
+
|
|
611
|
+
# Warn if child boundary points are near the edges of the parent grid
|
|
612
|
+
if (
|
|
613
|
+
i.where(mask).min() < 0
|
|
614
|
+
or i.where(mask).max() > nxp - 2
|
|
615
|
+
or j.where(mask).min() < 0
|
|
616
|
+
or j.where(mask).max() > nyp - 2
|
|
617
|
+
):
|
|
483
618
|
logging.warning(
|
|
484
|
-
"Some
|
|
619
|
+
f"Some wet points on the {direction}ern boundary of the child grid lie very close to the edges of the parent grid."
|
|
485
620
|
)
|
|
486
621
|
|
|
487
622
|
return i, j
|
|
488
623
|
|
|
489
624
|
|
|
490
|
-
def update_indices_if_on_parent_land(
|
|
625
|
+
def update_indices_if_on_parent_land(
|
|
626
|
+
i_eta: xr.DataArray,
|
|
627
|
+
i_xi: xr.DataArray,
|
|
628
|
+
grid_location: str,
|
|
629
|
+
parent_grid_ds: xr.Dataset,
|
|
630
|
+
) -> tuple[xr.DataArray, xr.DataArray]:
|
|
491
631
|
"""Finds points that are in the parent land mask but not land masked in the child
|
|
492
632
|
and replaces parent indices with nearest neighbor wet points.
|
|
493
633
|
|
|
@@ -581,13 +721,88 @@ def update_indices_if_on_parent_land(i_eta, i_xi, grid_location, parent_grid_ds)
|
|
|
581
721
|
return i_eta, i_xi
|
|
582
722
|
|
|
583
723
|
|
|
584
|
-
def
|
|
724
|
+
def _interpolate_parent(
|
|
725
|
+
parent_da: xr.DataArray, child_da: xr.DataArray
|
|
726
|
+
) -> xr.DataArray:
|
|
727
|
+
"""
|
|
728
|
+
Interpolate data from a parent grid onto a child grid using linear interpolation.
|
|
729
|
+
|
|
730
|
+
Parameters
|
|
731
|
+
----------
|
|
732
|
+
parent_da : xr.DataArray
|
|
733
|
+
The data array on the parent grid. Must have coordinates `lon_rho` and `lat_rho`.
|
|
734
|
+
child_da : xr.DataArray
|
|
735
|
+
The target child grid data array. Must have coordinates `lon_rho` and `lat_rho`.
|
|
736
|
+
|
|
737
|
+
Returns
|
|
738
|
+
-------
|
|
739
|
+
xr.DataArray
|
|
740
|
+
The interpolated data on the child grid, with dimensions ("eta_rho", "xi_rho").
|
|
741
|
+
"""
|
|
742
|
+
points = np.column_stack(
|
|
743
|
+
(parent_da.lon_rho.values.ravel(), parent_da.lat_rho.values.ravel())
|
|
744
|
+
)
|
|
745
|
+
xi = (child_da.lon_rho.values, child_da.lat_rho.values)
|
|
746
|
+
values = parent_da.values.ravel()
|
|
747
|
+
|
|
748
|
+
parent_interpolated = griddata(points, values, xi, method="linear")
|
|
749
|
+
return xr.DataArray(parent_interpolated, dims=("eta_rho", "xi_rho"))
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
def modify_child_mask(
|
|
753
|
+
parent_grid_ds: xr.Dataset,
|
|
754
|
+
child_grid_ds: xr.Dataset,
|
|
755
|
+
boundaries: dict = {"south": True, "east": True, "north": True, "west": True},
|
|
756
|
+
):
|
|
757
|
+
"""Adjust the child gridmask to align with the parent grid.
|
|
758
|
+
|
|
759
|
+
The mask of the child grid is adjusted using a weighted sum based on the boundary distance.
|
|
760
|
+
|
|
761
|
+
Parameters
|
|
762
|
+
----------
|
|
763
|
+
parent_grid_ds : xarray.Dataset
|
|
764
|
+
The parent grid dataset containing `mask_rho` (land-sea mask).
|
|
765
|
+
|
|
766
|
+
child_grid_ds : xarray.Dataset
|
|
767
|
+
The child grid dataset whose `mask_rho` will be modified.
|
|
768
|
+
|
|
769
|
+
boundaries : dict, optional
|
|
770
|
+
A dictionary specifying which boundaries should be modified. Expected keys:
|
|
771
|
+
- `"south"` (bool): Whether to adjust the southern boundary.
|
|
772
|
+
- `"east"` (bool): Whether to adjust the eastern boundary.
|
|
773
|
+
- `"north"` (bool): Whether to adjust the northern boundary.
|
|
774
|
+
- `"west"` (bool): Whether to adjust the western boundary.
|
|
775
|
+
Defaults to modifying all boundaries.
|
|
776
|
+
|
|
777
|
+
Returns
|
|
778
|
+
-------
|
|
779
|
+
xarray.Dataset
|
|
780
|
+
The updated child grid dataset with modified mask (`mask_rho`).
|
|
781
|
+
"""
|
|
782
|
+
# regrid parent mask onto child grid
|
|
783
|
+
mask_parent_interpolated = _interpolate_parent(
|
|
784
|
+
parent_grid_ds["mask_rho"], child_grid_ds["mask_rho"]
|
|
785
|
+
)
|
|
786
|
+
|
|
787
|
+
# compute weight based on distance
|
|
788
|
+
alpha = compute_boundary_distance(child_grid_ds["mask_rho"], boundaries)
|
|
789
|
+
|
|
790
|
+
# update child mask to be weighted sum between original child and interpolated parent
|
|
791
|
+
child_mask = (
|
|
792
|
+
alpha * child_grid_ds["mask_rho"] + (1 - alpha) * mask_parent_interpolated
|
|
793
|
+
)
|
|
794
|
+
child_grid_ds["mask_rho"] = xr.where(child_mask >= 0.5, 1, 0)
|
|
795
|
+
|
|
796
|
+
return child_grid_ds
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
def modify_child_topography(
|
|
585
800
|
parent_grid_ds,
|
|
586
801
|
child_grid_ds,
|
|
587
802
|
boundaries={"south": True, "east": True, "north": True, "west": True},
|
|
588
803
|
hmin=5.0,
|
|
589
804
|
):
|
|
590
|
-
"""Adjust the child grid topography
|
|
805
|
+
"""Adjust the child grid topography to align with the parent grid.
|
|
591
806
|
|
|
592
807
|
The topography of the child grid is adjusted using a weighted sum based on the boundary distance,
|
|
593
808
|
and the depth values are clipped to enforce a minimum depth constraint.
|
|
@@ -595,10 +810,10 @@ def modify_child_topography_and_mask(
|
|
|
595
810
|
Parameters
|
|
596
811
|
----------
|
|
597
812
|
parent_grid_ds : xarray.Dataset
|
|
598
|
-
The parent grid dataset containing `h` (topography)
|
|
813
|
+
The parent grid dataset containing `h` (topography).
|
|
599
814
|
|
|
600
815
|
child_grid_ds : xarray.Dataset
|
|
601
|
-
The child grid dataset whose `h`
|
|
816
|
+
The child grid dataset whose `h` will be modified.
|
|
602
817
|
|
|
603
818
|
boundaries : dict, optional
|
|
604
819
|
A dictionary specifying which boundaries should be modified. Expected keys:
|
|
@@ -616,39 +831,21 @@ def modify_child_topography_and_mask(
|
|
|
616
831
|
Returns
|
|
617
832
|
-------
|
|
618
833
|
xarray.Dataset
|
|
619
|
-
The updated child grid dataset with modified topography (`h`)
|
|
834
|
+
The updated child grid dataset with modified topography (`h`).
|
|
620
835
|
"""
|
|
621
|
-
# regrid parent
|
|
622
|
-
|
|
623
|
-
(parent_grid_ds.lon_rho.values.ravel(), parent_grid_ds.lat_rho.values.ravel())
|
|
624
|
-
)
|
|
625
|
-
xi = (child_grid_ds.lon_rho.values, child_grid_ds.lat_rho.values)
|
|
626
|
-
|
|
627
|
-
values = parent_grid_ds["h"].values.ravel()
|
|
628
|
-
h_parent_interpolated = griddata(points, values, xi, method="linear")
|
|
629
|
-
h_parent_interpolated = xr.DataArray(
|
|
630
|
-
h_parent_interpolated, dims=("eta_rho", "xi_rho")
|
|
631
|
-
)
|
|
632
|
-
|
|
633
|
-
values = parent_grid_ds["mask_rho"].values.ravel()
|
|
634
|
-
mask_parent_interpolated = griddata(points, values, xi, method="linear")
|
|
635
|
-
mask_parent_interpolated = xr.DataArray(
|
|
636
|
-
mask_parent_interpolated, dims=("eta_rho", "xi_rho")
|
|
637
|
-
)
|
|
836
|
+
# regrid parent mask onto child grid
|
|
837
|
+
h_parent_interpolated = _interpolate_parent(parent_grid_ds["h"], child_grid_ds["h"])
|
|
638
838
|
|
|
639
839
|
# compute weight based on distance
|
|
640
840
|
alpha = compute_boundary_distance(child_grid_ds["mask_rho"], boundaries)
|
|
641
|
-
|
|
841
|
+
|
|
842
|
+
# update child topography to be weighted sum between original child and interpolated parent
|
|
642
843
|
child_grid_ds["h"] = (
|
|
643
844
|
alpha * child_grid_ds["h"] + (1 - alpha) * h_parent_interpolated
|
|
644
845
|
)
|
|
645
|
-
# Clip depth on modified child topography
|
|
646
|
-
child_grid_ds["h"] = _clip_depth(child_grid_ds["h"], hmin)
|
|
647
846
|
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
)
|
|
651
|
-
child_grid_ds["mask_rho"] = xr.where(child_mask >= 0.5, 1, 0)
|
|
847
|
+
# Clip depth on modified child topography
|
|
848
|
+
child_grid_ds["h"] = clip_depth(child_grid_ds["h"], hmin)
|
|
652
849
|
|
|
653
850
|
return child_grid_ds
|
|
654
851
|
|