roms-tools 2.3.0__py3-none-any.whl → 2.5.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.yml +1 -0
- roms_tools/__init__.py +2 -1
- roms_tools/analysis/roms_output.py +81 -98
- roms_tools/plot.py +4 -2
- roms_tools/setup/boundary_forcing.py +207 -208
- roms_tools/setup/datasets.py +149 -33
- roms_tools/setup/grid.py +35 -102
- roms_tools/setup/initial_conditions.py +179 -132
- roms_tools/setup/nesting.py +239 -86
- roms_tools/setup/river_forcing.py +266 -128
- roms_tools/setup/surface_forcing.py +137 -76
- roms_tools/setup/tides.py +10 -36
- roms_tools/setup/topography.py +25 -2
- roms_tools/setup/utils.py +52 -82
- roms_tools/tests/test_analysis/test_roms_output.py +233 -70
- roms_tools/tests/test_setup/test_boundary_forcing.py +283 -57
- 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/boundary_forcing.zarr/.zattrs +5 -3
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zmetadata +156 -121
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/.zarray +2 -2
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/.zattrs +2 -1
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/bry_time/.zarray +2 -2
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/bry_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/bry_time/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_north/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_south/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_north/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_north/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_west/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_west/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 +4 -4
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zmetadata +4 -4
- 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/mask_coarse/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_rho/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_u/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_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 +2 -1
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zmetadata +6 -4
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Cs_r/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Cs_w/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NH4/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NO3/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/PO4/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/abs_time/.zattrs +1 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatSi/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ocean_time/.zattrs +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/spC/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spCaCO3/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spFe/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 +56 -0
- 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/.zarray +22 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_location/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_location/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/.zmetadata +56 -0
- 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/.zarray +22 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_location/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_location/0.0 +0 -0
- roms_tools/tests/test_setup/test_grid.py +0 -13
- roms_tools/tests/test_setup/test_initial_conditions.py +220 -66
- roms_tools/tests/test_setup/test_nesting.py +139 -118
- roms_tools/tests/test_setup/test_river_forcing.py +583 -293
- roms_tools/tests/test_setup/test_surface_forcing.py +149 -73
- roms_tools/tests/test_setup/test_tides.py +4 -16
- roms_tools/tests/test_setup/test_utils.py +1 -0
- roms_tools/tests/test_setup/test_validation.py +34 -2
- roms_tools/tests/{test_utils.py → test_tiling/test_partition.py} +1 -1
- roms_tools/tiling/partition.py +338 -0
- roms_tools/utils.py +66 -333
- roms_tools/vertical_coordinate.py +54 -133
- {roms_tools-2.3.0.dist-info → roms_tools-2.5.0.dist-info}/METADATA +1 -1
- {roms_tools-2.3.0.dist-info → roms_tools-2.5.0.dist-info}/RECORD +303 -290
- {roms_tools-2.3.0.dist-info → roms_tools-2.5.0.dist-info}/WHEEL +1 -1
- {roms_tools-2.3.0.dist-info → roms_tools-2.5.0.dist-info}/LICENSE +0 -0
- {roms_tools-2.3.0.dist-info → roms_tools-2.5.0.dist-info}/top_level.txt +0 -0
|
@@ -3,13 +3,14 @@ import numpy as np
|
|
|
3
3
|
from scipy.ndimage import label
|
|
4
4
|
import logging
|
|
5
5
|
import importlib.metadata
|
|
6
|
-
from typing import Dict, Union, List
|
|
6
|
+
from typing import Dict, Union, List, Optional
|
|
7
7
|
from dataclasses import dataclass, field
|
|
8
8
|
from datetime import datetime
|
|
9
9
|
import matplotlib.pyplot as plt
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
from roms_tools import Grid
|
|
12
12
|
from roms_tools.regrid import LateralRegrid, VerticalRegrid
|
|
13
|
+
from roms_tools.utils import save_datasets
|
|
13
14
|
from roms_tools.vertical_coordinate import compute_depth
|
|
14
15
|
from roms_tools.plot import _section_plot, _line_plot
|
|
15
16
|
from roms_tools.utils import (
|
|
@@ -21,7 +22,6 @@ from roms_tools.setup.datasets import GLORYSDataset, CESMBGCDataset
|
|
|
21
22
|
from roms_tools.setup.utils import (
|
|
22
23
|
get_variable_metadata,
|
|
23
24
|
group_dataset,
|
|
24
|
-
save_datasets,
|
|
25
25
|
get_target_coords,
|
|
26
26
|
rotate_velocities,
|
|
27
27
|
compute_barotropic_velocity,
|
|
@@ -43,10 +43,14 @@ class BoundaryForcing:
|
|
|
43
43
|
----------
|
|
44
44
|
grid : Grid
|
|
45
45
|
Object representing the grid information.
|
|
46
|
-
start_time : datetime
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
start_time : datetime, optional
|
|
47
|
+
The start time of the desired surface forcing data. This time is used to filter the dataset
|
|
48
|
+
to include only records on or after this time, with a single record at or before this time.
|
|
49
|
+
If no time filtering is desired, set it to None. Default is None.
|
|
50
|
+
end_time : datetime, optional
|
|
51
|
+
The end time of the desired surface forcing data. This time is used to filter the dataset
|
|
52
|
+
to include only records on or before this time, with a single record at or after this time.
|
|
53
|
+
If no time filtering is desired, set it to None. Default is None.
|
|
50
54
|
boundaries : Dict[str, bool], optional
|
|
51
55
|
Dictionary specifying which boundaries are forced (south, east, north, west). Default is all True.
|
|
52
56
|
source : Dict[str, Union[str, Path, List[Union[str, Path]]], bool]
|
|
@@ -66,10 +70,14 @@ class BoundaryForcing:
|
|
|
66
70
|
- "physics": for physical atmospheric forcing.
|
|
67
71
|
- "bgc": for biogeochemical forcing.
|
|
68
72
|
|
|
69
|
-
apply_2d_horizontal_fill: bool, optional
|
|
73
|
+
apply_2d_horizontal_fill : bool, optional
|
|
70
74
|
Indicates whether to perform a two-dimensional horizontal fill on the source data prior to regridding to boundaries.
|
|
71
75
|
If `False`, a one-dimensional horizontal fill is performed separately on each of the four regridded boundaries.
|
|
72
76
|
Defaults to `False`.
|
|
77
|
+
adjust_depth_for_sea_surface_height : bool, optional
|
|
78
|
+
Whether to account for sea surface height (`zeta`) variations when computing depth coordinates.
|
|
79
|
+
This adjustment is only applicable for `type="physics"`, as for biogeochemical fields usually `zeta` is not available.
|
|
80
|
+
Defaults to `False`.
|
|
73
81
|
model_reference_date : datetime, optional
|
|
74
82
|
Reference date for the model. Default is January 1, 2000.
|
|
75
83
|
use_dask: bool, optional
|
|
@@ -92,8 +100,8 @@ class BoundaryForcing:
|
|
|
92
100
|
"""
|
|
93
101
|
|
|
94
102
|
grid: Grid
|
|
95
|
-
start_time: datetime
|
|
96
|
-
end_time: datetime
|
|
103
|
+
start_time: Optional[datetime] = None
|
|
104
|
+
end_time: Optional[datetime] = None
|
|
97
105
|
boundaries: Dict[str, bool] = field(
|
|
98
106
|
default_factory=lambda: {
|
|
99
107
|
"south": True,
|
|
@@ -105,6 +113,7 @@ class BoundaryForcing:
|
|
|
105
113
|
source: Dict[str, Union[str, Path, List[Union[str, Path]]]]
|
|
106
114
|
type: str = "physics"
|
|
107
115
|
apply_2d_horizontal_fill: bool = False
|
|
116
|
+
adjust_depth_for_sea_surface_height: bool = False
|
|
108
117
|
model_reference_date: datetime = datetime(2000, 1, 1)
|
|
109
118
|
use_dask: bool = False
|
|
110
119
|
bypass_validation: bool = False
|
|
@@ -114,15 +123,21 @@ class BoundaryForcing:
|
|
|
114
123
|
def __post_init__(self):
|
|
115
124
|
|
|
116
125
|
self._input_checks()
|
|
126
|
+
# Dataset for depth coordinates
|
|
127
|
+
object.__setattr__(self, "ds_depth_coords", xr.Dataset())
|
|
128
|
+
|
|
117
129
|
target_coords = get_target_coords(self.grid)
|
|
118
130
|
|
|
119
131
|
data = self._get_data()
|
|
120
132
|
|
|
121
133
|
if self.apply_2d_horizontal_fill:
|
|
134
|
+
|
|
122
135
|
data.choose_subdomain(
|
|
123
136
|
target_coords,
|
|
124
137
|
buffer_points=20, # lateral fill needs good buffer from data margin
|
|
125
138
|
)
|
|
139
|
+
# Enforce double precision to ensure reproducibility
|
|
140
|
+
data.convert_to_float64()
|
|
126
141
|
data.extrapolate_deepest_to_bottom()
|
|
127
142
|
data.apply_lateral_fill()
|
|
128
143
|
|
|
@@ -150,17 +165,20 @@ class BoundaryForcing:
|
|
|
150
165
|
)
|
|
151
166
|
|
|
152
167
|
if not self.apply_2d_horizontal_fill:
|
|
168
|
+
# Enforce double precision to ensure reproducibility
|
|
169
|
+
bdry_data.convert_to_float64()
|
|
153
170
|
bdry_data.extrapolate_deepest_to_bottom()
|
|
154
171
|
|
|
155
172
|
processed_fields = {}
|
|
156
173
|
|
|
157
|
-
#
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
174
|
+
# vector fields (velocities) are only present in physics datasets
|
|
175
|
+
if self.type == "physics":
|
|
176
|
+
# lateral regridding of vector fields
|
|
177
|
+
vector_var_names = [
|
|
178
|
+
name
|
|
179
|
+
for name, info in self.variable_info.items()
|
|
180
|
+
if info["is_vector"]
|
|
181
|
+
]
|
|
164
182
|
lon = target_coords["lon"].isel(
|
|
165
183
|
**self.bdry_coords["vector"][direction]
|
|
166
184
|
)
|
|
@@ -176,6 +194,13 @@ class BoundaryForcing:
|
|
|
176
194
|
bdry_data.ds[bdry_data.var_names[var_name]]
|
|
177
195
|
)
|
|
178
196
|
|
|
197
|
+
if self.adjust_depth_for_sea_surface_height:
|
|
198
|
+
# Regrid sea surface height ('zeta') onto a 2-cell-wide margin.
|
|
199
|
+
# This is needed to correctly infer depth coordinates at u- and v-points along the boundary.
|
|
200
|
+
zeta_vector = lateral_regrid.apply(
|
|
201
|
+
bdry_data.ds[bdry_data.var_names["zeta"]]
|
|
202
|
+
)
|
|
203
|
+
|
|
179
204
|
# lateral regridding of tracer fields
|
|
180
205
|
tracer_var_names = [
|
|
181
206
|
name
|
|
@@ -209,6 +234,9 @@ class BoundaryForcing:
|
|
|
209
234
|
angle,
|
|
210
235
|
interpolate=True,
|
|
211
236
|
)
|
|
237
|
+
if self.adjust_depth_for_sea_surface_height:
|
|
238
|
+
zeta_u = interpolate_from_rho_to_u(zeta_vector)
|
|
239
|
+
zeta_v = interpolate_from_rho_to_v(zeta_vector)
|
|
212
240
|
|
|
213
241
|
# selection of outermost margin for u/v variables
|
|
214
242
|
for var_name in self.variable_info.keys():
|
|
@@ -218,6 +246,9 @@ class BoundaryForcing:
|
|
|
218
246
|
processed_fields[var_name] = processed_fields[
|
|
219
247
|
var_name
|
|
220
248
|
].isel(**self.bdry_coords[location][direction])
|
|
249
|
+
if self.adjust_depth_for_sea_surface_height:
|
|
250
|
+
zeta_u = zeta_u.isel(**self.bdry_coords["u"][direction])
|
|
251
|
+
zeta_v = zeta_v.isel(**self.bdry_coords["v"][direction])
|
|
221
252
|
|
|
222
253
|
if not self.apply_2d_horizontal_fill:
|
|
223
254
|
self._validate_1d_fill(
|
|
@@ -225,7 +256,20 @@ class BoundaryForcing:
|
|
|
225
256
|
direction,
|
|
226
257
|
bdry_data.dim_names["depth"],
|
|
227
258
|
)
|
|
228
|
-
|
|
259
|
+
for var_name in processed_fields.keys():
|
|
260
|
+
processed_fields[var_name] = apply_1d_horizontal_fill(
|
|
261
|
+
processed_fields[var_name]
|
|
262
|
+
)
|
|
263
|
+
if self.adjust_depth_for_sea_surface_height:
|
|
264
|
+
zeta_u = apply_1d_horizontal_fill(zeta_u)
|
|
265
|
+
zeta_v = apply_1d_horizontal_fill(zeta_v)
|
|
266
|
+
|
|
267
|
+
if self.adjust_depth_for_sea_surface_height:
|
|
268
|
+
zeta = processed_fields["zeta"]
|
|
269
|
+
else:
|
|
270
|
+
zeta = 0
|
|
271
|
+
zeta_u = 0
|
|
272
|
+
zeta_v = 0
|
|
229
273
|
|
|
230
274
|
var_names_dict = {}
|
|
231
275
|
for location in ["rho", "u", "v"]:
|
|
@@ -234,24 +278,22 @@ class BoundaryForcing:
|
|
|
234
278
|
for name, info in self.variable_info.items()
|
|
235
279
|
if info["location"] == location and info["is_3d"]
|
|
236
280
|
]
|
|
281
|
+
|
|
237
282
|
# compute layer depth coordinates
|
|
283
|
+
if len(var_names_dict["rho"]) > 0:
|
|
284
|
+
self._get_depth_coordinates(zeta, direction, "rho", "layer")
|
|
285
|
+
self._get_depth_coordinates(
|
|
286
|
+
zeta, direction, "rho", "interface"
|
|
287
|
+
) # only necessary for plotting
|
|
238
288
|
if len(var_names_dict["u"]) > 0 or len(var_names_dict["v"]) > 0:
|
|
239
|
-
self.
|
|
240
|
-
|
|
241
|
-
direction=direction,
|
|
242
|
-
additional_locations=["u", "v"],
|
|
243
|
-
)
|
|
244
|
-
else:
|
|
245
|
-
if len(var_names_dict["rho"]) > 0:
|
|
246
|
-
self._get_vertical_coordinates(
|
|
247
|
-
type="layer", direction=direction, additional_locations=[]
|
|
248
|
-
)
|
|
289
|
+
self._get_depth_coordinates(zeta_u, direction, "u", "layer")
|
|
290
|
+
self._get_depth_coordinates(zeta_v, direction, "v", "layer")
|
|
249
291
|
|
|
250
292
|
# vertical regridding
|
|
251
293
|
for location in ["rho", "u", "v"]:
|
|
252
294
|
if len(var_names_dict[location]) > 0:
|
|
253
295
|
vertical_regrid = VerticalRegrid(
|
|
254
|
-
self.
|
|
296
|
+
self.ds_depth_coords[f"layer_depth_{location}_{direction}"],
|
|
255
297
|
bdry_data.ds[bdry_data.dim_names["depth"]],
|
|
256
298
|
)
|
|
257
299
|
for var_name in var_names_dict[location]:
|
|
@@ -262,17 +304,16 @@ class BoundaryForcing:
|
|
|
262
304
|
|
|
263
305
|
# compute barotropic velocities
|
|
264
306
|
if "u" in self.variable_info and "v" in self.variable_info:
|
|
265
|
-
self.
|
|
266
|
-
|
|
267
|
-
direction=direction,
|
|
268
|
-
additional_locations=["u", "v"],
|
|
269
|
-
)
|
|
307
|
+
self._get_depth_coordinates(zeta_u, direction, "u", "interface")
|
|
308
|
+
self._get_depth_coordinates(zeta_v, direction, "v", "interface")
|
|
270
309
|
for location in ["u", "v"]:
|
|
271
310
|
processed_fields[
|
|
272
311
|
f"{location}bar"
|
|
273
312
|
] = compute_barotropic_velocity(
|
|
274
313
|
processed_fields[location],
|
|
275
|
-
self.
|
|
314
|
+
self.ds_depth_coords[
|
|
315
|
+
f"interface_depth_{location}_{direction}"
|
|
316
|
+
],
|
|
276
317
|
)
|
|
277
318
|
|
|
278
319
|
# Reorder dimensions
|
|
@@ -297,6 +338,18 @@ class BoundaryForcing:
|
|
|
297
338
|
object.__setattr__(self, "ds", ds)
|
|
298
339
|
|
|
299
340
|
def _input_checks(self):
|
|
341
|
+
# Check that start_time and end_time are both None or none of them is
|
|
342
|
+
if (self.start_time is None) != (self.end_time is None):
|
|
343
|
+
raise ValueError(
|
|
344
|
+
"Both `start_time` and `end_time` must be provided together as datetime objects or both should be None."
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
# Trigger a warning if both are None
|
|
348
|
+
if self.start_time is None and self.end_time is None:
|
|
349
|
+
logging.warning(
|
|
350
|
+
"Both `start_time` and `end_time` are None. No time filtering will be applied to the source data."
|
|
351
|
+
)
|
|
352
|
+
|
|
300
353
|
# Validate the 'type' parameter
|
|
301
354
|
if self.type not in ["physics", "bgc"]:
|
|
302
355
|
raise ValueError("`type` must be either 'physics' or 'bgc'.")
|
|
@@ -314,6 +367,29 @@ class BoundaryForcing:
|
|
|
314
367
|
{**self.source, "climatology": self.source.get("climatology", False)},
|
|
315
368
|
)
|
|
316
369
|
|
|
370
|
+
# Ensure adjust_depth_for_sea_surface_height is only used with type="physics"
|
|
371
|
+
if self.type == "bgc" and self.adjust_depth_for_sea_surface_height:
|
|
372
|
+
logging.warning(
|
|
373
|
+
"adjust_depth_for_sea_surface_height is not applicable for BGC fields. "
|
|
374
|
+
"Setting it to False."
|
|
375
|
+
)
|
|
376
|
+
object.__setattr__(self, "adjust_depth_for_sea_surface_height", False)
|
|
377
|
+
elif self.adjust_depth_for_sea_surface_height:
|
|
378
|
+
logging.info("Sea surface height will be used to adjust depth coordinates.")
|
|
379
|
+
else:
|
|
380
|
+
logging.info(
|
|
381
|
+
"Sea surface height will NOT be used to adjust depth coordinates."
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
if self.apply_2d_horizontal_fill:
|
|
385
|
+
logging.info(
|
|
386
|
+
"Applying 2D horizontal fill to the source data before regridding."
|
|
387
|
+
)
|
|
388
|
+
else:
|
|
389
|
+
logging.info(
|
|
390
|
+
"Applying 1D horizontal fill separately to each regridded boundary."
|
|
391
|
+
)
|
|
392
|
+
|
|
317
393
|
def _get_data(self):
|
|
318
394
|
|
|
319
395
|
data_dict = {
|
|
@@ -489,118 +565,80 @@ class BoundaryForcing:
|
|
|
489
565
|
|
|
490
566
|
object.__setattr__(self, "bdry_coords", bdry_coords)
|
|
491
567
|
|
|
492
|
-
def
|
|
493
|
-
self,
|
|
494
|
-
|
|
495
|
-
|
|
568
|
+
def _get_depth_coordinates(
|
|
569
|
+
self,
|
|
570
|
+
zeta: xr.DataArray | float,
|
|
571
|
+
direction: str,
|
|
572
|
+
location: str,
|
|
573
|
+
depth_type: str = "layer",
|
|
574
|
+
) -> None:
|
|
575
|
+
"""Compute and store depth coordinates for a specified boundary direction, grid
|
|
576
|
+
location, and depth type.
|
|
496
577
|
|
|
497
|
-
This method computes
|
|
498
|
-
|
|
499
|
-
|
|
578
|
+
This method efficiently computes depth coordinates along the specified boundary without
|
|
579
|
+
interpolating the entire domain topography. The computed depth values are stored in
|
|
580
|
+
`self.ds_depth_coords`.
|
|
500
581
|
|
|
501
582
|
Parameters
|
|
502
583
|
----------
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
-
|
|
506
|
-
-
|
|
507
|
-
|
|
584
|
+
zeta : xr.DataArray or float
|
|
585
|
+
Free-surface elevation (`zeta`). Can be:
|
|
586
|
+
- A scalar float value (constant sea surface height).
|
|
587
|
+
- An `xarray.DataArray` with spatial variations. If provided as an array, it may have a
|
|
588
|
+
time dimension, but must be **1D** (varying only in time).
|
|
508
589
|
direction : str
|
|
509
|
-
The direction
|
|
590
|
+
The boundary direction for which depth coordinates are computed. Must be one of:
|
|
510
591
|
- "north"
|
|
511
592
|
- "south"
|
|
512
593
|
- "east"
|
|
513
594
|
- "west"
|
|
595
|
+
location : str
|
|
596
|
+
Grid location at which depth is computed. Must be one of:
|
|
597
|
+
- `"rho"`: Depth at scalar grid points.
|
|
598
|
+
- `"u"`: Depth at U-velocity grid points.
|
|
599
|
+
- `"v"`: Depth at V-velocity grid points.
|
|
600
|
+
depth_type : str, optional
|
|
601
|
+
Type of depth coordinate to compute, either:
|
|
602
|
+
- `"layer"` (default): Depth at vertical layer midpoints.
|
|
603
|
+
- `"interface"`: Depth at vertical layer interfaces.
|
|
514
604
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
- "v": Computes depth coordinates for v points.
|
|
520
|
-
|
|
521
|
-
Updates
|
|
522
|
-
-------
|
|
523
|
-
self.grid.ds : xarray.Dataset
|
|
524
|
-
The dataset is updated with the following vertical depth coordinates:
|
|
525
|
-
- f"{type}_depth_rho_{direction}": Depth coordinates at rho points.
|
|
526
|
-
- f"{type}_depth_u_{direction}": Depth coordinates at u points (if applicable).
|
|
527
|
-
- f"{type}_depth_v_{direction}": Depth coordinates at v points (if applicable).
|
|
605
|
+
Notes
|
|
606
|
+
-----
|
|
607
|
+
- This method is optimized for boundary computations by selecting only the relevant margin
|
|
608
|
+
(2 grid cells) instead of interpolating the entire domain.
|
|
528
609
|
"""
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
layer_vars.append(f"{type}_depth_{location}_{direction}")
|
|
533
|
-
|
|
534
|
-
if all(layer_var in self.grid.ds for layer_var in layer_vars):
|
|
535
|
-
# Vertical coordinate data already exists
|
|
536
|
-
pass
|
|
537
|
-
|
|
538
|
-
elif f"{type}_depth_rho" in self.grid.ds:
|
|
539
|
-
depth = self.grid.ds[f"{type}_depth_rho"]
|
|
540
|
-
depth.attrs["long_name"] = f"{type} depth at rho-points"
|
|
541
|
-
depth.attrs["units"] = "m"
|
|
542
|
-
self.grid.ds[f"{type}_depth_rho_{direction}"] = depth.isel(
|
|
543
|
-
**self.bdry_coords["rho"][direction]
|
|
544
|
-
)
|
|
545
|
-
|
|
546
|
-
if "u" in additional_locations or "v" in additional_locations:
|
|
610
|
+
key = f"{depth_type}_depth_{location}_{direction}"
|
|
611
|
+
if key not in self.ds_depth_coords:
|
|
612
|
+
if location in ["u", "v"]:
|
|
547
613
|
# selection of margin consisting of 2 grid cells
|
|
548
|
-
depth = depth.isel(**self.bdry_coords["vector"][direction])
|
|
549
|
-
# interpolation
|
|
550
|
-
if "u" in additional_locations:
|
|
551
|
-
depth_u = interpolate_from_rho_to_u(depth)
|
|
552
|
-
depth_u.attrs["long_name"] = f"{type} depth at u-points"
|
|
553
|
-
depth_u.attrs["units"] = "m"
|
|
554
|
-
self.grid.ds[f"{type}_depth_u_{direction}"] = depth_u.isel(
|
|
555
|
-
**self.bdry_coords["u"][direction]
|
|
556
|
-
)
|
|
557
|
-
if "v" in additional_locations:
|
|
558
|
-
depth_v = interpolate_from_rho_to_v(depth)
|
|
559
|
-
depth_v.attrs["long_name"] = f"{type} depth at v-points"
|
|
560
|
-
depth_v.attrs["units"] = "m"
|
|
561
|
-
self.grid.ds[f"{type}_depth_v_{direction}"] = depth_v.isel(
|
|
562
|
-
**self.bdry_coords["v"][direction]
|
|
563
|
-
)
|
|
564
|
-
else:
|
|
565
|
-
if "u" in additional_locations or "v" in additional_locations:
|
|
566
614
|
h = self.grid.ds["h"].isel(**self.bdry_coords["vector"][direction])
|
|
615
|
+
if location == "u":
|
|
616
|
+
h = interpolate_from_rho_to_u(h)
|
|
617
|
+
h = h.isel(**self.bdry_coords["u"][direction])
|
|
618
|
+
elif location == "v":
|
|
619
|
+
h = interpolate_from_rho_to_v(h)
|
|
620
|
+
h = h.isel(**self.bdry_coords["v"][direction])
|
|
567
621
|
else:
|
|
568
622
|
h = self.grid.ds["h"].isel(**self.bdry_coords["rho"][direction])
|
|
569
|
-
|
|
623
|
+
|
|
624
|
+
if depth_type == "layer":
|
|
570
625
|
depth = compute_depth(
|
|
571
|
-
|
|
626
|
+
zeta, h, self.grid.hc, self.grid.ds.Cs_r, self.grid.ds.sigma_r
|
|
572
627
|
)
|
|
573
628
|
else:
|
|
574
629
|
depth = compute_depth(
|
|
575
|
-
|
|
630
|
+
zeta, h, self.grid.hc, self.grid.ds.Cs_w, self.grid.ds.sigma_w
|
|
576
631
|
)
|
|
577
632
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
depth_u = interpolate_from_rho_to_u(depth)
|
|
588
|
-
depth_v = interpolate_from_rho_to_v(depth)
|
|
589
|
-
# selection of outermost margin
|
|
590
|
-
depth_u.attrs["long_name"] = f"{type} depth at u-points"
|
|
591
|
-
depth_u.attrs["units"] = "m"
|
|
592
|
-
self.grid.ds[f"{type}_depth_u_{direction}"] = depth_u.isel(
|
|
593
|
-
**self.bdry_coords["u"][direction]
|
|
594
|
-
)
|
|
595
|
-
depth_v.attrs["long_name"] = f"{type} depth at v-points"
|
|
596
|
-
depth_v.attrs["units"] = "m"
|
|
597
|
-
self.grid.ds[f"{type}_depth_v_{direction}"] = depth_v.isel(
|
|
598
|
-
**self.bdry_coords["v"][direction]
|
|
599
|
-
)
|
|
600
|
-
else:
|
|
601
|
-
depth.attrs["long_name"] = f"{type} depth at rho-points"
|
|
602
|
-
depth.attrs["units"] = "m"
|
|
603
|
-
self.grid.ds[f"{type}_depth_rho_{direction}"] = depth
|
|
633
|
+
# Add metadata
|
|
634
|
+
depth.attrs.update(
|
|
635
|
+
{
|
|
636
|
+
"long_name": f"{depth_type} depth at {location}-points along {direction}ern boundary",
|
|
637
|
+
"units": "m",
|
|
638
|
+
}
|
|
639
|
+
)
|
|
640
|
+
|
|
641
|
+
self.ds_depth_coords[key] = depth
|
|
604
642
|
|
|
605
643
|
def _add_global_metadata(self, data, ds=None):
|
|
606
644
|
|
|
@@ -617,6 +655,10 @@ class BoundaryForcing:
|
|
|
617
655
|
ds.attrs["end_time"] = str(self.end_time)
|
|
618
656
|
ds.attrs["source"] = self.source["name"]
|
|
619
657
|
ds.attrs["model_reference_date"] = str(self.model_reference_date)
|
|
658
|
+
ds.attrs["apply_2d_horizontal_fill"] = str(self.apply_2d_horizontal_fill)
|
|
659
|
+
ds.attrs["adjust_depth_for_sea_surface_height"] = str(
|
|
660
|
+
self.adjust_depth_for_sea_surface_height
|
|
661
|
+
)
|
|
620
662
|
|
|
621
663
|
ds.attrs["theta_s"] = self.grid.ds.attrs["theta_s"]
|
|
622
664
|
ds.attrs["theta_b"] = self.grid.ds.attrs["theta_b"]
|
|
@@ -840,9 +882,10 @@ class BoundaryForcing:
|
|
|
840
882
|
mask = mask.isel(**self.bdry_coords[location][direction])
|
|
841
883
|
|
|
842
884
|
if "s_rho" in field.dims:
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
885
|
+
layer_depth = self.ds_depth_coords[f"layer_depth_{location}_{direction}"]
|
|
886
|
+
if self.adjust_depth_for_sea_surface_height:
|
|
887
|
+
layer_depth = layer_depth.isel(time=time)
|
|
888
|
+
field = field.assign_coords({"layer_depth": layer_depth})
|
|
846
889
|
if var_name.startswith(("u", "v", "ubar", "vbar", "zeta")):
|
|
847
890
|
vmax = max(field.max().values, -field.min().values)
|
|
848
891
|
vmin = -vmax
|
|
@@ -859,19 +902,11 @@ class BoundaryForcing:
|
|
|
859
902
|
|
|
860
903
|
if len(field.dims) == 2:
|
|
861
904
|
if layer_contours:
|
|
862
|
-
|
|
863
|
-
additional_locations = ["u", "v"]
|
|
864
|
-
else:
|
|
865
|
-
additional_locations = []
|
|
866
|
-
self._get_vertical_coordinates(
|
|
867
|
-
type="interface",
|
|
868
|
-
direction=direction,
|
|
869
|
-
additional_locations=additional_locations,
|
|
870
|
-
)
|
|
871
|
-
|
|
872
|
-
interface_depth = self.grid.ds[
|
|
905
|
+
interface_depth = self.ds_depth_coords[
|
|
873
906
|
f"interface_depth_{location}_{direction}"
|
|
874
907
|
]
|
|
908
|
+
if self.adjust_depth_for_sea_surface_height:
|
|
909
|
+
interface_depth = interface_depth.isel(time=time)
|
|
875
910
|
# restrict number of layer_contours to 10 for the sake of plot clearity
|
|
876
911
|
nr_layers = len(interface_depth["s_w"])
|
|
877
912
|
selected_layers = np.linspace(
|
|
@@ -883,7 +918,7 @@ class BoundaryForcing:
|
|
|
883
918
|
interface_depth = None
|
|
884
919
|
|
|
885
920
|
_section_plot(
|
|
886
|
-
field
|
|
921
|
+
field,
|
|
887
922
|
interface_depth=interface_depth,
|
|
888
923
|
title=title,
|
|
889
924
|
kwargs=kwargs,
|
|
@@ -895,37 +930,21 @@ class BoundaryForcing:
|
|
|
895
930
|
def save(
|
|
896
931
|
self,
|
|
897
932
|
filepath: Union[str, Path],
|
|
898
|
-
|
|
899
|
-
np_xi: int = None,
|
|
900
|
-
group: bool = False,
|
|
933
|
+
group: bool = True,
|
|
901
934
|
) -> None:
|
|
902
935
|
"""Save the boundary forcing fields to one or more netCDF4 files.
|
|
903
936
|
|
|
904
|
-
This method saves the dataset
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
1. **Single File Mode (default)**:
|
|
908
|
-
- If both `np_eta` and `np_xi` are `None`, the entire dataset is saved as a single netCDF4 file.
|
|
909
|
-
- The file is named based on the `filepath`, with `.nc` automatically appended.
|
|
910
|
-
|
|
911
|
-
2. **Partitioned Mode**:
|
|
912
|
-
- If either `np_eta` or `np_xi` is specified, the dataset is partitioned into spatial tiles along the `eta` and `xi` axes.
|
|
913
|
-
- Each tile is saved as a separate netCDF4 file, and filenames are modified with an index (e.g., `"filepath_YYYYMM.0.nc"`, `"filepath_YYYYMM.1.nc"`).
|
|
914
|
-
|
|
915
|
-
Additionally, if `group` is set to `True`, the dataset is first grouped into temporal subsets, resulting in multiple grouped files before partitioning and saving.
|
|
937
|
+
This method saves the dataset to disk as either a single netCDF4 file or multiple files, depending on the `group` parameter.
|
|
938
|
+
If `group` is `True`, the dataset is divided into subsets (e.g., monthly or yearly) based on the temporal frequency
|
|
939
|
+
of the data, and each subset is saved to a separate file.
|
|
916
940
|
|
|
917
941
|
Parameters
|
|
918
942
|
----------
|
|
919
943
|
filepath : Union[str, Path]
|
|
920
|
-
The base path and filename for the output
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
The number of partitions along the `eta` direction. If `None`, no spatial partitioning is performed.
|
|
925
|
-
np_xi : int, optional
|
|
926
|
-
The number of partitions along the `xi` direction. If `None`, no spatial partitioning is performed.
|
|
927
|
-
group: bool, optional
|
|
928
|
-
If `True`, groups the dataset into multiple files based on temporal data frequency. Defaults to `False`.
|
|
944
|
+
The base path and filename for the output file(s). If `group` is `True`, the filenames will include additional
|
|
945
|
+
time-based information (e.g., year or month) to distinguish the subsets.
|
|
946
|
+
group : bool, optional
|
|
947
|
+
Whether to divide the dataset into multiple files based on temporal frequency. Defaults to `True`.
|
|
929
948
|
|
|
930
949
|
Returns
|
|
931
950
|
-------
|
|
@@ -940,12 +959,6 @@ class BoundaryForcing:
|
|
|
940
959
|
if filepath.suffix == ".nc":
|
|
941
960
|
filepath = filepath.with_suffix("")
|
|
942
961
|
|
|
943
|
-
if self.use_dask:
|
|
944
|
-
from dask.diagnostics import ProgressBar
|
|
945
|
-
|
|
946
|
-
with ProgressBar():
|
|
947
|
-
self.ds.load()
|
|
948
|
-
|
|
949
962
|
if group:
|
|
950
963
|
dataset_list, output_filenames = group_dataset(self.ds, str(filepath))
|
|
951
964
|
else:
|
|
@@ -953,7 +966,7 @@ class BoundaryForcing:
|
|
|
953
966
|
output_filenames = [str(filepath)]
|
|
954
967
|
|
|
955
968
|
saved_filenames = save_datasets(
|
|
956
|
-
dataset_list, output_filenames,
|
|
969
|
+
dataset_list, output_filenames, use_dask=self.use_dask
|
|
957
970
|
)
|
|
958
971
|
|
|
959
972
|
return saved_filenames
|
|
@@ -975,7 +988,6 @@ class BoundaryForcing:
|
|
|
975
988
|
cls,
|
|
976
989
|
filepath: Union[str, Path],
|
|
977
990
|
use_dask: bool = False,
|
|
978
|
-
bypass_validation: bool = False,
|
|
979
991
|
) -> "BoundaryForcing":
|
|
980
992
|
"""Create an instance of the BoundaryForcing class from a YAML file.
|
|
981
993
|
|
|
@@ -985,10 +997,6 @@ class BoundaryForcing:
|
|
|
985
997
|
The path to the YAML file from which the parameters will be read.
|
|
986
998
|
use_dask: bool, optional
|
|
987
999
|
Indicates whether to use dask for processing. If True, data is processed with dask; if False, data is processed eagerly. Defaults to False.
|
|
988
|
-
bypass_validation: bool, optional
|
|
989
|
-
Indicates whether to skip validation checks in the processed data. When set to True,
|
|
990
|
-
the validation process that ensures no NaN values exist at wet points
|
|
991
|
-
in the processed dataset is bypassed. Defaults to False.
|
|
992
1000
|
|
|
993
1001
|
Returns
|
|
994
1002
|
-------
|
|
@@ -1001,24 +1009,22 @@ class BoundaryForcing:
|
|
|
1001
1009
|
params = _from_yaml(cls, filepath)
|
|
1002
1010
|
|
|
1003
1011
|
# Create and return an instance of InitialConditions
|
|
1004
|
-
return cls(
|
|
1005
|
-
grid=grid, **params, use_dask=use_dask, bypass_validation=bypass_validation
|
|
1006
|
-
)
|
|
1012
|
+
return cls(grid=grid, **params, use_dask=use_dask)
|
|
1007
1013
|
|
|
1008
1014
|
|
|
1009
|
-
def apply_1d_horizontal_fill(
|
|
1010
|
-
"""Forward and backward fill NaN values in horizontal
|
|
1015
|
+
def apply_1d_horizontal_fill(data_array: xr.DataArray) -> xr.DataArray:
|
|
1016
|
+
"""Forward and backward fill NaN values in a single horizontal dimension for open
|
|
1017
|
+
boundaries.
|
|
1011
1018
|
|
|
1012
1019
|
Parameters
|
|
1013
1020
|
----------
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
`xarray.DataArray`.
|
|
1021
|
+
data_array : xarray.DataArray
|
|
1022
|
+
The data array to be updated.
|
|
1017
1023
|
|
|
1018
1024
|
Returns
|
|
1019
1025
|
-------
|
|
1020
|
-
|
|
1021
|
-
The updated
|
|
1026
|
+
xarray.DataArray
|
|
1027
|
+
The updated data array with NaN values filled.
|
|
1022
1028
|
|
|
1023
1029
|
Raises
|
|
1024
1030
|
------
|
|
@@ -1027,29 +1033,22 @@ def apply_1d_horizontal_fill(processed_fields: dict) -> dict:
|
|
|
1027
1033
|
"""
|
|
1028
1034
|
|
|
1029
1035
|
horizontal_dims = ["eta_rho", "eta_v", "xi_rho", "xi_u"]
|
|
1036
|
+
selected_horizontal_dim = None
|
|
1030
1037
|
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
)
|
|
1040
|
-
selected_horizontal_dim = dim
|
|
1041
|
-
|
|
1042
|
-
if selected_horizontal_dim is None:
|
|
1043
|
-
raise ValueError(
|
|
1044
|
-
f"No valid horizontal dimension found for variable '{var_name}'."
|
|
1045
|
-
)
|
|
1038
|
+
# Determine the horizontal dimension to fill
|
|
1039
|
+
for dim in horizontal_dims:
|
|
1040
|
+
if dim in data_array.dims:
|
|
1041
|
+
if selected_horizontal_dim is not None:
|
|
1042
|
+
raise ValueError(
|
|
1043
|
+
f"More than one horizontal dimension found in variable '{data_array.name}'."
|
|
1044
|
+
)
|
|
1045
|
+
selected_horizontal_dim = dim
|
|
1046
1046
|
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
)
|
|
1051
|
-
processed_fields[var_name] = one_dim_fill(
|
|
1052
|
-
filled, selected_horizontal_dim, direction="backward"
|
|
1047
|
+
if selected_horizontal_dim is None:
|
|
1048
|
+
raise ValueError(
|
|
1049
|
+
f"No valid horizontal dimension found for variable '{data_array.name}'."
|
|
1053
1050
|
)
|
|
1054
1051
|
|
|
1055
|
-
|
|
1052
|
+
# Forward and backward fill in the horizontal direction
|
|
1053
|
+
filled = one_dim_fill(data_array, selected_horizontal_dim, direction="forward")
|
|
1054
|
+
return one_dim_fill(filled, selected_horizontal_dim, direction="backward")
|