roms-tools 1.5.0__py3-none-any.whl → 1.6.1__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/_version.py +1 -1
- roms_tools/setup/boundary_forcing.py +263 -100
- roms_tools/setup/datasets.py +169 -39
- roms_tools/setup/fill.py +0 -36
- roms_tools/setup/grid.py +1 -1
- roms_tools/setup/initial_conditions.py +108 -73
- roms_tools/setup/regrid.py +43 -98
- roms_tools/setup/surface_forcing.py +104 -82
- roms_tools/setup/tides.py +76 -48
- roms_tools/setup/utils.py +25 -53
- roms_tools/tests/test_setup/test_boundary_forcing.py +84 -47
- 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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 +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zmetadata +1 -1
- 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/iron/0.0.0 +0 -0
- 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/nox/0.0.0 +0 -0
- 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_from_climatology.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zmetadata +1 -1
- 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/.zmetadata +7 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/.zattrs +3 -0
- 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_south/0.0.0 +0 -0
- 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_south/0.0.0 +0 -0
- 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/0.0.0 +0 -0
- 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/0.0.0 +0 -0
- 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/0.0 +0 -0
- 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/0.0 +0 -0
- 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/0.0.0 +0 -0
- 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/0.0.0 +0 -0
- 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/0.0 +0 -0
- 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/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/.zattrs +1 -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/.zattrs +1 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/.zattrs +1 -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/.zattrs +1 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/.zmetadata +1 -1
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/Tair/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/lwrad/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/qair/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/rain/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/swrad/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/uwnd/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/vwnd/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/.zmetadata +1 -1
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/Tair/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/lwrad/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/qair/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/rain/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/swrad/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/uwnd/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/vwnd/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK_ALT_CO2/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC_ALT_CO2/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOC/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOCr/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DON/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DONr/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOP/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOPr/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Fe/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Lig/0.0.0.0 +0 -0
- 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/O2/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/SiO3/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatC/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatChl/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatFe/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatP/0.0.0.0 +0 -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/diazC/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazChl/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazFe/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazP/0.0.0.0 +0 -0
- 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/spChl/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/spP/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/initial_conditions_with_bgc_from_climatology.zarr/zooC/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/.zmetadata +1 -1
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/Tair/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/lwrad/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/qair/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/rain/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/swrad/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/uwnd/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/surface_forcing.zarr/vwnd/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/.zmetadata +4 -2
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/omega/.zattrs +3 -1
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/pot_Im/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/pot_Re/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ssh_Im/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ssh_Re/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Im/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Re/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Im/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Re/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_datasets.py +79 -21
- roms_tools/tests/test_setup/test_fill.py +18 -105
- roms_tools/tests/test_setup/test_initial_conditions.py +29 -25
- roms_tools/tests/test_setup/test_regrid.py +2 -8
- roms_tools/tests/test_setup/test_surface_forcing.py +49 -29
- roms_tools/tests/test_setup/test_tides.py +7 -5
- {roms_tools-1.5.0.dist-info → roms_tools-1.6.1.dist-info}/METADATA +13 -3
- {roms_tools-1.5.0.dist-info → roms_tools-1.6.1.dist-info}/RECORD +239 -239
- {roms_tools-1.5.0.dist-info → roms_tools-1.6.1.dist-info}/WHEEL +1 -1
- {roms_tools-1.5.0.dist-info → roms_tools-1.6.1.dist-info}/LICENSE +0 -0
- {roms_tools-1.5.0.dist-info → roms_tools-1.6.1.dist-info}/top_level.txt +0 -0
roms_tools/_version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# Do not change! Do not track in version control!
|
|
2
|
-
__version__ = "1.
|
|
2
|
+
__version__ = "1.6.1"
|
|
@@ -3,24 +3,24 @@ import numpy as np
|
|
|
3
3
|
import pandas as pd
|
|
4
4
|
import yaml
|
|
5
5
|
import importlib.metadata
|
|
6
|
+
import warnings
|
|
6
7
|
from typing import Dict, Union, List
|
|
7
8
|
from dataclasses import dataclass, field, asdict
|
|
8
9
|
from roms_tools.setup.grid import Grid
|
|
9
|
-
from roms_tools.setup.
|
|
10
|
-
from roms_tools.setup.regrid import _lateral_regrid, _vertical_regrid
|
|
10
|
+
from roms_tools.setup.regrid import LateralRegrid, VerticalRegrid
|
|
11
11
|
from datetime import datetime
|
|
12
12
|
from roms_tools.setup.datasets import GLORYSDataset, CESMBGCDataset
|
|
13
13
|
from roms_tools.setup.utils import (
|
|
14
|
-
nan_check,
|
|
15
|
-
substitute_nans_by_fillvalue,
|
|
16
14
|
get_variable_metadata,
|
|
17
15
|
group_dataset,
|
|
18
16
|
save_datasets,
|
|
19
17
|
get_target_coords,
|
|
20
18
|
rotate_velocities,
|
|
21
19
|
compute_barotropic_velocity,
|
|
22
|
-
_extrapolate_deepest_to_bottom,
|
|
23
20
|
transpose_dimensions,
|
|
21
|
+
one_dim_fill,
|
|
22
|
+
nan_check,
|
|
23
|
+
substitute_nans_by_fillvalue,
|
|
24
24
|
)
|
|
25
25
|
from roms_tools.setup.plot import _section_plot, _line_plot
|
|
26
26
|
import matplotlib.pyplot as plt
|
|
@@ -60,6 +60,10 @@ class BoundaryForcing:
|
|
|
60
60
|
|
|
61
61
|
model_reference_date : datetime, optional
|
|
62
62
|
Reference date for the model. Default is January 1, 2000.
|
|
63
|
+
apply_2d_horizontal_fill: bool, optional
|
|
64
|
+
Indicates whether to perform a two-dimensional horizontal fill on the source data prior to regridding to boundaries.
|
|
65
|
+
If `False`, a one-dimensional horizontal fill is performed separately on each of the four regridded boundaries.
|
|
66
|
+
Defaults to `False`.
|
|
63
67
|
use_dask: bool, optional
|
|
64
68
|
Indicates whether to use dask for processing. If True, data is processed with dask; if False, data is processed eagerly. Defaults to False.
|
|
65
69
|
|
|
@@ -89,6 +93,7 @@ class BoundaryForcing:
|
|
|
89
93
|
source: Dict[str, Union[str, Path, List[Union[str, Path]]]]
|
|
90
94
|
type: str = "physics"
|
|
91
95
|
model_reference_date: datetime = datetime(2000, 1, 1)
|
|
96
|
+
apply_2d_horizontal_fill: bool = False
|
|
92
97
|
use_dask: bool = False
|
|
93
98
|
|
|
94
99
|
ds: xr.Dataset = field(init=False, repr=False)
|
|
@@ -99,31 +104,42 @@ class BoundaryForcing:
|
|
|
99
104
|
target_coords = get_target_coords(self.grid)
|
|
100
105
|
|
|
101
106
|
data = self._get_data()
|
|
102
|
-
data.choose_subdomain(
|
|
103
|
-
latitude_range=[
|
|
104
|
-
target_coords["lat"].min().values,
|
|
105
|
-
target_coords["lat"].max().values,
|
|
106
|
-
],
|
|
107
|
-
longitude_range=[
|
|
108
|
-
target_coords["lon"].min().values,
|
|
109
|
-
target_coords["lon"].max().values,
|
|
110
|
-
],
|
|
111
|
-
margin=2,
|
|
112
|
-
straddle=target_coords["straddle"],
|
|
113
|
-
)
|
|
114
107
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
108
|
+
if self.apply_2d_horizontal_fill:
|
|
109
|
+
data.choose_subdomain(
|
|
110
|
+
target_coords,
|
|
111
|
+
buffer_points=20, # lateral fill needs good buffer from data margin
|
|
112
|
+
)
|
|
113
|
+
data.extrapolate_deepest_to_bottom()
|
|
114
|
+
data.apply_lateral_fill()
|
|
120
115
|
|
|
116
|
+
variable_info = self._set_variable_info(data)
|
|
121
117
|
bdry_coords = get_boundary_info()
|
|
122
118
|
ds = xr.Dataset()
|
|
119
|
+
|
|
123
120
|
for direction in ["south", "east", "north", "west"]:
|
|
124
121
|
if self.boundaries[direction]:
|
|
125
122
|
|
|
126
|
-
|
|
123
|
+
bdry_target_coords = {
|
|
124
|
+
"lat": target_coords["lat"].isel(
|
|
125
|
+
**bdry_coords["vector"][direction]
|
|
126
|
+
),
|
|
127
|
+
"lon": target_coords["lon"].isel(
|
|
128
|
+
**bdry_coords["vector"][direction]
|
|
129
|
+
),
|
|
130
|
+
"straddle": target_coords["straddle"],
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
bdry_data = data.choose_subdomain(
|
|
134
|
+
bdry_target_coords,
|
|
135
|
+
buffer_points=3,
|
|
136
|
+
return_copy=True,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
if not self.apply_2d_horizontal_fill:
|
|
140
|
+
bdry_data.extrapolate_deepest_to_bottom()
|
|
141
|
+
|
|
142
|
+
processed_fields = {}
|
|
127
143
|
|
|
128
144
|
# lateral regridding of vector fields
|
|
129
145
|
vector_var_names = [
|
|
@@ -132,9 +148,15 @@ class BoundaryForcing:
|
|
|
132
148
|
if len(vector_var_names) > 0:
|
|
133
149
|
lon = target_coords["lon"].isel(**bdry_coords["vector"][direction])
|
|
134
150
|
lat = target_coords["lat"].isel(**bdry_coords["vector"][direction])
|
|
135
|
-
|
|
136
|
-
|
|
151
|
+
lateral_regrid = LateralRegrid(
|
|
152
|
+
{"lat": lat, "lon": lon}, bdry_data.dim_names
|
|
137
153
|
)
|
|
154
|
+
for var_name in vector_var_names:
|
|
155
|
+
if var_name in bdry_data.var_names.keys():
|
|
156
|
+
processed_fields[var_name] = lateral_regrid.apply(
|
|
157
|
+
bdry_data.ds[bdry_data.var_names[var_name]]
|
|
158
|
+
)
|
|
159
|
+
|
|
138
160
|
# lateral regridding of tracer fields
|
|
139
161
|
tracer_var_names = [
|
|
140
162
|
name
|
|
@@ -144,30 +166,38 @@ class BoundaryForcing:
|
|
|
144
166
|
if len(tracer_var_names) > 0:
|
|
145
167
|
lon = target_coords["lon"].isel(**bdry_coords["rho"][direction])
|
|
146
168
|
lat = target_coords["lat"].isel(**bdry_coords["rho"][direction])
|
|
147
|
-
|
|
148
|
-
|
|
169
|
+
lateral_regrid = LateralRegrid(
|
|
170
|
+
{"lat": lat, "lon": lon}, bdry_data.dim_names
|
|
149
171
|
)
|
|
172
|
+
for var_name in tracer_var_names:
|
|
173
|
+
if var_name in bdry_data.var_names.keys():
|
|
174
|
+
processed_fields[var_name] = lateral_regrid.apply(
|
|
175
|
+
bdry_data.ds[bdry_data.var_names[var_name]]
|
|
176
|
+
)
|
|
150
177
|
|
|
151
178
|
# rotation of velocities and interpolation to u/v points
|
|
152
179
|
if "u" in variable_info and "v" in variable_info:
|
|
153
180
|
angle = target_coords["angle"].isel(
|
|
154
181
|
**bdry_coords["vector"][direction]
|
|
155
182
|
)
|
|
156
|
-
(
|
|
157
|
-
|
|
158
|
-
|
|
183
|
+
(processed_fields["u"], processed_fields["v"],) = rotate_velocities(
|
|
184
|
+
processed_fields["u"],
|
|
185
|
+
processed_fields["v"],
|
|
159
186
|
angle,
|
|
160
187
|
interpolate=True,
|
|
161
188
|
)
|
|
162
189
|
|
|
163
190
|
# selection of outermost margin for u/v variables
|
|
164
|
-
for
|
|
165
|
-
if
|
|
166
|
-
location = variable_info[
|
|
191
|
+
for var_name in variable_info.keys():
|
|
192
|
+
if var_name in processed_fields:
|
|
193
|
+
location = variable_info[var_name]["location"]
|
|
167
194
|
if location in ["u", "v"]:
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
)
|
|
195
|
+
processed_fields[var_name] = processed_fields[
|
|
196
|
+
var_name
|
|
197
|
+
].isel(**bdry_coords[location][direction])
|
|
198
|
+
|
|
199
|
+
if not self.apply_2d_horizontal_fill:
|
|
200
|
+
processed_fields = apply_1d_horizontal_fill(processed_fields)
|
|
171
201
|
|
|
172
202
|
# vertical regridding
|
|
173
203
|
for location in ["rho", "u", "v"]:
|
|
@@ -177,53 +207,47 @@ class BoundaryForcing:
|
|
|
177
207
|
if info["location"] == location and info["is_3d"]
|
|
178
208
|
]
|
|
179
209
|
if len(var_names) > 0:
|
|
180
|
-
|
|
181
|
-
data,
|
|
210
|
+
vertical_regrid = VerticalRegrid(
|
|
182
211
|
self.grid.ds[f"layer_depth_{location}"].isel(
|
|
183
|
-
**bdry_coords[location][direction]
|
|
212
|
+
**bdry_coords[location][direction]
|
|
184
213
|
),
|
|
185
|
-
|
|
186
|
-
var_names,
|
|
214
|
+
bdry_data.ds[bdry_data.dim_names["depth"]],
|
|
187
215
|
)
|
|
216
|
+
for var_name in var_names:
|
|
217
|
+
if var_name in processed_fields:
|
|
218
|
+
processed_fields[var_name] = vertical_regrid.apply(
|
|
219
|
+
processed_fields[var_name]
|
|
220
|
+
)
|
|
188
221
|
|
|
189
222
|
# compute barotropic velocities
|
|
190
223
|
if "u" in variable_info and "v" in variable_info:
|
|
191
|
-
for
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
224
|
+
for var_name in ["u", "v"]:
|
|
225
|
+
processed_fields[
|
|
226
|
+
f"{var_name}bar"
|
|
227
|
+
] = compute_barotropic_velocity(
|
|
228
|
+
processed_fields[var_name],
|
|
229
|
+
self.grid.ds[f"interface_depth_{var_name}"].isel(
|
|
230
|
+
**bdry_coords[var_name][direction]
|
|
196
231
|
),
|
|
197
232
|
)
|
|
198
233
|
|
|
199
234
|
# Reorder dimensions
|
|
200
|
-
for
|
|
201
|
-
|
|
235
|
+
for var_name in processed_fields.keys():
|
|
236
|
+
processed_fields[var_name] = transpose_dimensions(
|
|
237
|
+
processed_fields[var_name]
|
|
238
|
+
)
|
|
202
239
|
|
|
203
240
|
# Write the boundary data into dataset
|
|
204
|
-
ds = self._write_into_dataset(direction,
|
|
241
|
+
ds = self._write_into_dataset(direction, processed_fields, ds)
|
|
205
242
|
|
|
206
243
|
# Add global information
|
|
207
244
|
ds = self._add_global_metadata(data, ds)
|
|
208
245
|
|
|
209
|
-
|
|
210
|
-
# this check works only for 2D fields because for 3D I extrapolate to bottom which eliminates NaNs
|
|
211
|
-
for direction in ["south", "east", "north", "west"]:
|
|
212
|
-
if self.boundaries[direction]:
|
|
213
|
-
if type == "physics":
|
|
214
|
-
nan_check(
|
|
215
|
-
ds[f"zeta_{direction}"].isel(bry_time=0),
|
|
216
|
-
self.grid.ds.mask_rho.isel(**bdry_coords["rho"][direction]),
|
|
217
|
-
)
|
|
218
|
-
elif type == "bgc":
|
|
219
|
-
nan_check(
|
|
220
|
-
ds[f"ALK_{direction}"].isel(bry_time=0, s_rho=-1),
|
|
221
|
-
self.grid.ds.mask_rho.isel(**bdry_coords["rho"][direction]),
|
|
222
|
-
)
|
|
246
|
+
self._validate(ds, variable_info, bdry_coords)
|
|
223
247
|
|
|
224
248
|
# substitute NaNs over land by a fill value to avoid blow-up of ROMS
|
|
225
|
-
for
|
|
226
|
-
ds[
|
|
249
|
+
for var_name in ds.data_vars:
|
|
250
|
+
ds[var_name] = substitute_nans_by_fillvalue(ds[var_name])
|
|
227
251
|
|
|
228
252
|
object.__setattr__(self, "ds", ds)
|
|
229
253
|
|
|
@@ -335,25 +359,27 @@ class BoundaryForcing:
|
|
|
335
359
|
}
|
|
336
360
|
elif self.type == "bgc":
|
|
337
361
|
variable_info = {}
|
|
338
|
-
for
|
|
339
|
-
variable_info[
|
|
362
|
+
for var_name in data.var_names.keys():
|
|
363
|
+
variable_info[var_name] = default_info
|
|
340
364
|
|
|
341
365
|
return variable_info
|
|
342
366
|
|
|
343
|
-
def _write_into_dataset(self, direction,
|
|
367
|
+
def _write_into_dataset(self, direction, processed_fields, ds=None):
|
|
344
368
|
if ds is None:
|
|
345
369
|
ds = xr.Dataset()
|
|
346
370
|
|
|
347
371
|
d_meta = get_variable_metadata()
|
|
348
372
|
|
|
349
|
-
for
|
|
350
|
-
ds[f"{
|
|
373
|
+
for var_name in processed_fields.keys():
|
|
374
|
+
ds[f"{var_name}_{direction}"] = processed_fields[var_name].astype(
|
|
375
|
+
np.float32
|
|
376
|
+
)
|
|
351
377
|
|
|
352
|
-
ds[f"{
|
|
378
|
+
ds[f"{var_name}_{direction}"].attrs[
|
|
353
379
|
"long_name"
|
|
354
|
-
] = f"{direction}ern boundary {d_meta[
|
|
380
|
+
] = f"{direction}ern boundary {d_meta[var_name]['long_name']}"
|
|
355
381
|
|
|
356
|
-
ds[f"{
|
|
382
|
+
ds[f"{var_name}_{direction}"].attrs["units"] = d_meta[var_name]["units"]
|
|
357
383
|
|
|
358
384
|
# Gracefully handle dropping variables that might not be present
|
|
359
385
|
variables_to_drop = [
|
|
@@ -371,7 +397,7 @@ class BoundaryForcing:
|
|
|
371
397
|
"lat_v",
|
|
372
398
|
"lon_v",
|
|
373
399
|
]
|
|
374
|
-
existing_vars = [
|
|
400
|
+
existing_vars = [var_name for var_name in variables_to_drop if var_name in ds]
|
|
375
401
|
ds = ds.drop_vars(existing_vars)
|
|
376
402
|
|
|
377
403
|
return ds
|
|
@@ -480,9 +506,76 @@ class BoundaryForcing:
|
|
|
480
506
|
|
|
481
507
|
return ds
|
|
482
508
|
|
|
509
|
+
def _validate(self, ds, variable_info, bdry_coords):
|
|
510
|
+
"""Validate the dataset for NaN values at the first time step based on the fill
|
|
511
|
+
method used.
|
|
512
|
+
|
|
513
|
+
Parameters
|
|
514
|
+
----------
|
|
515
|
+
ds : xarray.Dataset
|
|
516
|
+
The dataset to validate.
|
|
517
|
+
|
|
518
|
+
variable_info : dict
|
|
519
|
+
A dictionary containing metadata about the variables, including their locations (e.g., 'rho', 'u', 'v').
|
|
520
|
+
|
|
521
|
+
bdry_coords : dict
|
|
522
|
+
A dictionary containing the boundary coordinates for each variable location.
|
|
523
|
+
|
|
524
|
+
Raises
|
|
525
|
+
------
|
|
526
|
+
ValueError
|
|
527
|
+
If NaN values are found in any of the specified variables at wet points,
|
|
528
|
+
indicating incomplete data coverage.
|
|
529
|
+
|
|
530
|
+
Notes
|
|
531
|
+
-----
|
|
532
|
+
Validation is performed on the initial boundary time step (`bry_time=0`) for each
|
|
533
|
+
variable in the dataset. If the `apply_2d_horizontal_fill` attribute is set to False,
|
|
534
|
+
a warning is issued instead of a strict NaN check, as the data may not be reliably validated.
|
|
535
|
+
Conversely, if `apply_2d_horizontal_fill` is True, a strict NaN check is performed, raising
|
|
536
|
+
a ValueError if any NaN values are detected.
|
|
537
|
+
"""
|
|
538
|
+
if self.apply_2d_horizontal_fill:
|
|
539
|
+
# Strict NaN check with ValueError makes sense to be applied
|
|
540
|
+
for var_name in variable_info:
|
|
541
|
+
location = variable_info[var_name]["location"]
|
|
542
|
+
|
|
543
|
+
# Select the appropriate mask based on variable location
|
|
544
|
+
if location == "rho":
|
|
545
|
+
mask = self.grid.ds.mask_rho
|
|
546
|
+
elif location == "u":
|
|
547
|
+
mask = self.grid.ds.mask_u
|
|
548
|
+
elif location == "v":
|
|
549
|
+
mask = self.grid.ds.mask_v
|
|
550
|
+
else:
|
|
551
|
+
continue # Skip if location is not recognized
|
|
552
|
+
|
|
553
|
+
for direction in ["south", "east", "north", "west"]:
|
|
554
|
+
if self.boundaries[direction]:
|
|
555
|
+
bdry_var_name = f"{var_name}_{direction}"
|
|
556
|
+
|
|
557
|
+
# Check for NaN values at the first time step using the nan_check function
|
|
558
|
+
nan_check(
|
|
559
|
+
ds[bdry_var_name].isel(bry_time=0),
|
|
560
|
+
mask.isel(**bdry_coords[location][direction]),
|
|
561
|
+
)
|
|
562
|
+
else:
|
|
563
|
+
# Can't apply strict NaN check because land values haven't been filled before regridding step; instead warn user
|
|
564
|
+
for direction in ["south", "east", "north", "west"]:
|
|
565
|
+
if self.boundaries[direction]:
|
|
566
|
+
for var_name in variable_info:
|
|
567
|
+
bdry_var_name = f"{var_name}_{direction}"
|
|
568
|
+
if ds[bdry_var_name].isel(bry_time=0).isnull().any().values:
|
|
569
|
+
warnings.warn(
|
|
570
|
+
f"NaN values detected in regridded variables along the {direction}ern boundary. This may indicate that the entire boundary is on land in the source data, or that the source data does not cover this boundary.",
|
|
571
|
+
UserWarning,
|
|
572
|
+
)
|
|
573
|
+
# Break after the first warning for this direction to avoid duplicates
|
|
574
|
+
break
|
|
575
|
+
|
|
483
576
|
def plot(
|
|
484
577
|
self,
|
|
485
|
-
|
|
578
|
+
var_name,
|
|
486
579
|
time=0,
|
|
487
580
|
layer_contours=False,
|
|
488
581
|
) -> None:
|
|
@@ -490,7 +583,7 @@ class BoundaryForcing:
|
|
|
490
583
|
|
|
491
584
|
Parameters
|
|
492
585
|
----------
|
|
493
|
-
|
|
586
|
+
var_name : str
|
|
494
587
|
The name of the boundary forcing field to plot. Options include:
|
|
495
588
|
|
|
496
589
|
- "temp_{direction}": Potential temperature,
|
|
@@ -550,37 +643,44 @@ class BoundaryForcing:
|
|
|
550
643
|
Raises
|
|
551
644
|
------
|
|
552
645
|
ValueError
|
|
553
|
-
If the specified
|
|
646
|
+
If the specified var_name is not one of the valid options.
|
|
554
647
|
"""
|
|
555
648
|
|
|
556
|
-
if
|
|
557
|
-
raise ValueError(f"Variable '{
|
|
649
|
+
if var_name not in self.ds:
|
|
650
|
+
raise ValueError(f"Variable '{var_name}' is not found in dataset.")
|
|
651
|
+
|
|
652
|
+
field = self.ds[var_name].isel(bry_time=time)
|
|
653
|
+
|
|
654
|
+
if self.use_dask:
|
|
655
|
+
from dask.diagnostics import ProgressBar
|
|
656
|
+
|
|
657
|
+
with ProgressBar():
|
|
658
|
+
field = field.load()
|
|
558
659
|
|
|
559
|
-
field = self.ds[varname].isel(bry_time=time).load()
|
|
560
660
|
title = field.long_name
|
|
561
661
|
|
|
562
662
|
if "s_rho" in field.dims:
|
|
563
|
-
if
|
|
663
|
+
if var_name.startswith(("u_", "ubar_")):
|
|
564
664
|
point = "u"
|
|
565
|
-
elif
|
|
665
|
+
elif var_name.startswith(("v_", "vbar_")):
|
|
566
666
|
point = "v"
|
|
567
667
|
else:
|
|
568
668
|
point = "rho"
|
|
569
|
-
direction =
|
|
669
|
+
direction = var_name.split("_")[-1]
|
|
570
670
|
|
|
571
671
|
layer_depth, interface_depth = self._get_coordinates(direction, point)
|
|
572
672
|
|
|
573
673
|
field = field.assign_coords({"layer_depth": layer_depth})
|
|
574
674
|
|
|
575
675
|
# chose colorbar
|
|
576
|
-
if
|
|
676
|
+
if var_name.startswith(("u", "v", "ubar", "vbar", "zeta")):
|
|
577
677
|
vmax = max(field.max().values, -field.min().values)
|
|
578
678
|
vmin = -vmax
|
|
579
679
|
cmap = plt.colormaps.get_cmap("RdBu_r")
|
|
580
680
|
else:
|
|
581
681
|
vmax = field.max().values
|
|
582
682
|
vmin = field.min().values
|
|
583
|
-
if
|
|
683
|
+
if var_name.startswith(("temp", "salt")):
|
|
584
684
|
cmap = plt.colormaps.get_cmap("YlOrRd")
|
|
585
685
|
else:
|
|
586
686
|
cmap = plt.colormaps.get_cmap("YlGn")
|
|
@@ -606,24 +706,26 @@ class BoundaryForcing:
|
|
|
606
706
|
_line_plot(field, title=title)
|
|
607
707
|
|
|
608
708
|
def save(
|
|
609
|
-
self,
|
|
709
|
+
self,
|
|
710
|
+
filepath: Union[str, Path],
|
|
711
|
+
np_eta: int = None,
|
|
712
|
+
np_xi: int = None,
|
|
713
|
+
group: bool = False,
|
|
610
714
|
) -> None:
|
|
611
|
-
"""Save the boundary forcing fields to netCDF4 files.
|
|
612
|
-
|
|
613
|
-
This method saves the dataset by grouping it into subsets based on the data frequency. The subsets are then written
|
|
614
|
-
to one or more netCDF4 files. The filenames of the output files reflect the temporal coverage of the data.
|
|
715
|
+
"""Save the boundary forcing fields to one or more netCDF4 files.
|
|
615
716
|
|
|
616
|
-
|
|
717
|
+
This method saves the dataset either as a single file or as multiple files depending on the partitioning and grouping options.
|
|
718
|
+
The dataset can be saved in two modes:
|
|
617
719
|
|
|
618
|
-
|
|
720
|
+
1. **Single File Mode (default)**:
|
|
721
|
+
- If both `np_eta` and `np_xi` are `None`, the entire dataset is saved as a single netCDF4 file.
|
|
722
|
+
- The file is named based on the `filepath`, with `.nc` automatically appended.
|
|
619
723
|
|
|
620
|
-
|
|
621
|
-
|
|
724
|
+
2. **Partitioned Mode**:
|
|
725
|
+
- If either `np_eta` or `np_xi` is specified, the dataset is partitioned into spatial tiles along the `eta` and `xi` axes.
|
|
726
|
+
- 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"`).
|
|
622
727
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
- If either `np_eta` or `np_xi` is specified, the dataset is divided into spatial tiles along the eta-axis and xi-axis.
|
|
626
|
-
- Each spatial tile is saved as a separate netCDF4 file.
|
|
728
|
+
Additionally, if `group` is set to `True`, the dataset is first grouped into temporal subsets, resulting in multiple grouped files before partitioning and saving.
|
|
627
729
|
|
|
628
730
|
Parameters
|
|
629
731
|
----------
|
|
@@ -635,6 +737,8 @@ class BoundaryForcing:
|
|
|
635
737
|
The number of partitions along the `eta` direction. If `None`, no spatial partitioning is performed.
|
|
636
738
|
np_xi : int, optional
|
|
637
739
|
The number of partitions along the `xi` direction. If `None`, no spatial partitioning is performed.
|
|
740
|
+
group: bool, optional
|
|
741
|
+
If `True`, groups the dataset into multiple files based on temporal data frequency. Defaults to `False`.
|
|
638
742
|
|
|
639
743
|
Returns
|
|
640
744
|
-------
|
|
@@ -649,7 +753,18 @@ class BoundaryForcing:
|
|
|
649
753
|
if filepath.suffix == ".nc":
|
|
650
754
|
filepath = filepath.with_suffix("")
|
|
651
755
|
|
|
652
|
-
|
|
756
|
+
if self.use_dask:
|
|
757
|
+
from dask.diagnostics import ProgressBar
|
|
758
|
+
|
|
759
|
+
with ProgressBar():
|
|
760
|
+
self.ds.load()
|
|
761
|
+
|
|
762
|
+
if group:
|
|
763
|
+
dataset_list, output_filenames = group_dataset(self.ds, str(filepath))
|
|
764
|
+
else:
|
|
765
|
+
dataset_list = [self.ds]
|
|
766
|
+
output_filenames = [str(filepath)]
|
|
767
|
+
|
|
653
768
|
saved_filenames = save_datasets(
|
|
654
769
|
dataset_list, output_filenames, np_eta=np_eta, np_xi=np_xi
|
|
655
770
|
)
|
|
@@ -703,7 +818,7 @@ class BoundaryForcing:
|
|
|
703
818
|
# Write header
|
|
704
819
|
file.write(header)
|
|
705
820
|
# Write YAML data
|
|
706
|
-
yaml.dump(yaml_data, file, default_flow_style=False)
|
|
821
|
+
yaml.dump(yaml_data, file, default_flow_style=False, sort_keys=False)
|
|
707
822
|
|
|
708
823
|
@classmethod
|
|
709
824
|
def from_yaml(
|
|
@@ -798,3 +913,51 @@ def get_boundary_info():
|
|
|
798
913
|
}
|
|
799
914
|
|
|
800
915
|
return bdry_coords
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
def apply_1d_horizontal_fill(processed_fields: dict) -> dict:
|
|
919
|
+
"""Forward and backward fill NaN values in horizontal direction for open boundaries.
|
|
920
|
+
|
|
921
|
+
Parameters
|
|
922
|
+
----------
|
|
923
|
+
processed_fields : dict
|
|
924
|
+
A dictionary of variables to be updated, where each value is an
|
|
925
|
+
`xarray.DataArray`.
|
|
926
|
+
|
|
927
|
+
Returns
|
|
928
|
+
-------
|
|
929
|
+
dict of str : xarray.DataArray
|
|
930
|
+
The updated dictionary of variables, with NaN values filled.
|
|
931
|
+
|
|
932
|
+
Raises
|
|
933
|
+
------
|
|
934
|
+
ValueError
|
|
935
|
+
If more than one horizontal dimension is found or none at all.
|
|
936
|
+
"""
|
|
937
|
+
|
|
938
|
+
horizontal_dims = ["eta_rho", "eta_v", "xi_rho", "xi_u"]
|
|
939
|
+
|
|
940
|
+
for var_name in processed_fields.keys():
|
|
941
|
+
selected_horizontal_dim = None
|
|
942
|
+
# Determine the horizontal dimension to fill
|
|
943
|
+
for dim in horizontal_dims:
|
|
944
|
+
if dim in processed_fields[var_name].dims:
|
|
945
|
+
if selected_horizontal_dim is not None:
|
|
946
|
+
raise ValueError(
|
|
947
|
+
f"More than one horizontal dimension found in variable '{var_name}'."
|
|
948
|
+
)
|
|
949
|
+
selected_horizontal_dim = dim
|
|
950
|
+
|
|
951
|
+
if selected_horizontal_dim is None:
|
|
952
|
+
raise ValueError(
|
|
953
|
+
f"No valid horizontal dimension found for variable '{var_name}'."
|
|
954
|
+
)
|
|
955
|
+
# Forward and backward fill in the horizontal direction
|
|
956
|
+
filled = one_dim_fill(
|
|
957
|
+
processed_fields[var_name], selected_horizontal_dim, direction="forward"
|
|
958
|
+
)
|
|
959
|
+
processed_fields[var_name] = one_dim_fill(
|
|
960
|
+
filled, selected_horizontal_dim, direction="backward"
|
|
961
|
+
)
|
|
962
|
+
|
|
963
|
+
return processed_fields
|