roms-tools 1.4.2__py3-none-any.whl → 1.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- roms_tools/_version.py +1 -1
- roms_tools/setup/boundary_forcing.py +448 -130
- roms_tools/setup/datasets.py +186 -52
- roms_tools/setup/fill.py +2 -2
- roms_tools/setup/initial_conditions.py +217 -70
- roms_tools/setup/regrid.py +143 -0
- roms_tools/setup/surface_forcing.py +159 -73
- roms_tools/setup/tides.py +141 -54
- roms_tools/setup/utils.py +229 -62
- roms_tools/tests/test_setup/test_boundary_forcing.py +42 -32
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zmetadata +1 -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_north/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_north/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_north/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_north/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_north/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_north/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_north/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_north/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_north/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_north/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_north/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_north/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_north/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_north/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_north/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_north/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 +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/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zmetadata +8 -1
- 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_north/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/salt_west/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_north/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/temp_west/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_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_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/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zmetadata +1 -1
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/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 +55 -113
- roms_tools/tests/test_setup/test_initial_conditions.py +21 -21
- roms_tools/tests/test_setup/test_regrid.py +53 -0
- roms_tools/tests/test_setup/test_surface_forcing.py +21 -3
- roms_tools/tests/test_setup/test_tides.py +1 -1
- {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/METADATA +13 -4
- {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/RECORD +277 -276
- {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/WHEEL +1 -1
- roms_tools/setup/mixins.py +0 -227
- {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/LICENSE +0 -0
- {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/top_level.txt +0 -0
|
@@ -12,15 +12,19 @@ from roms_tools.setup.utils import (
|
|
|
12
12
|
substitute_nans_by_fillvalue,
|
|
13
13
|
get_variable_metadata,
|
|
14
14
|
save_datasets,
|
|
15
|
+
get_target_coords,
|
|
16
|
+
rotate_velocities,
|
|
17
|
+
compute_barotropic_velocity,
|
|
18
|
+
transpose_dimensions,
|
|
15
19
|
)
|
|
16
|
-
from roms_tools.setup.
|
|
20
|
+
from roms_tools.setup.regrid import LateralRegrid, VerticalRegrid
|
|
17
21
|
from roms_tools.setup.plot import _plot, _section_plot, _profile_plot, _line_plot
|
|
18
22
|
import matplotlib.pyplot as plt
|
|
19
23
|
from pathlib import Path
|
|
20
24
|
|
|
21
25
|
|
|
22
26
|
@dataclass(frozen=True, kw_only=True)
|
|
23
|
-
class InitialConditions
|
|
27
|
+
class InitialConditions:
|
|
24
28
|
"""Represents initial conditions for ROMS, including physical and biogeochemical
|
|
25
29
|
data.
|
|
26
30
|
|
|
@@ -85,58 +89,103 @@ class InitialConditions(ROMSToolsMixins):
|
|
|
85
89
|
def __post_init__(self):
|
|
86
90
|
|
|
87
91
|
self._input_checks()
|
|
88
|
-
lon, lat, angle, straddle = super()._get_target_lon_lat()
|
|
89
92
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
latitude_range=[lat.min().values, lat.max().values],
|
|
93
|
-
longitude_range=[lon.min().values, lon.max().values],
|
|
94
|
-
margin=2,
|
|
95
|
-
straddle=straddle,
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
vars_2d = ["zeta"]
|
|
99
|
-
vars_3d = ["temp", "salt", "u", "v"]
|
|
100
|
-
data_vars = super()._regrid_data(data, vars_2d, vars_3d, lon, lat)
|
|
101
|
-
data_vars = super()._process_velocities(data_vars, angle, "u", "v")
|
|
93
|
+
processed_fields = {}
|
|
94
|
+
processed_fields = self._process_data(processed_fields, type="physics")
|
|
102
95
|
|
|
103
96
|
if self.bgc_source is not None:
|
|
104
|
-
|
|
105
|
-
bgc_data.choose_subdomain(
|
|
106
|
-
latitude_range=[lat.min().values, lat.max().values],
|
|
107
|
-
longitude_range=[lon.min().values, lon.max().values],
|
|
108
|
-
margin=2,
|
|
109
|
-
straddle=straddle,
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
vars_2d = []
|
|
113
|
-
vars_3d = bgc_data.var_names.keys()
|
|
114
|
-
bgc_data_vars = super()._regrid_data(bgc_data, vars_2d, vars_3d, lon, lat)
|
|
97
|
+
processed_fields = self._process_data(processed_fields, type="bgc")
|
|
115
98
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
# Combine data variables from physical and biogeochemical sources
|
|
123
|
-
data_vars.update(bgc_data_vars)
|
|
99
|
+
for var_name in processed_fields.keys():
|
|
100
|
+
processed_fields[var_name] = transpose_dimensions(
|
|
101
|
+
processed_fields[var_name]
|
|
102
|
+
)
|
|
124
103
|
|
|
125
104
|
d_meta = get_variable_metadata()
|
|
126
|
-
ds = self._write_into_dataset(
|
|
105
|
+
ds = self._write_into_dataset(processed_fields, d_meta)
|
|
127
106
|
|
|
128
107
|
ds = self._add_global_metadata(ds)
|
|
129
108
|
|
|
130
|
-
|
|
131
|
-
# NaN values at wet points indicate that the raw data did not cover the domain, and the following will raise a ValueError
|
|
132
|
-
nan_check(ds["zeta"].squeeze(), self.grid.ds.mask_rho)
|
|
109
|
+
self._validate(ds)
|
|
133
110
|
|
|
134
111
|
# substitute NaNs over land by a fill value to avoid blow-up of ROMS
|
|
135
|
-
for
|
|
136
|
-
ds[
|
|
112
|
+
for var_name in ds.data_vars:
|
|
113
|
+
ds[var_name] = substitute_nans_by_fillvalue(ds[var_name])
|
|
137
114
|
|
|
138
115
|
object.__setattr__(self, "ds", ds)
|
|
139
116
|
|
|
117
|
+
def _process_data(self, processed_fields, type="physics"):
|
|
118
|
+
|
|
119
|
+
target_coords = get_target_coords(self.grid)
|
|
120
|
+
|
|
121
|
+
if type == "physics":
|
|
122
|
+
data = self._get_data()
|
|
123
|
+
else:
|
|
124
|
+
data = self._get_bgc_data()
|
|
125
|
+
|
|
126
|
+
data.choose_subdomain(
|
|
127
|
+
target_coords,
|
|
128
|
+
buffer_points=20, # lateral fill needs good buffer from data margin
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
data.extrapolate_deepest_to_bottom()
|
|
132
|
+
data.apply_lateral_fill()
|
|
133
|
+
|
|
134
|
+
variable_info = self._set_variable_info(data, type=type)
|
|
135
|
+
var_names = variable_info.keys()
|
|
136
|
+
|
|
137
|
+
# lateral regridding
|
|
138
|
+
lateral_regrid = LateralRegrid(target_coords, data.dim_names)
|
|
139
|
+
for var_name in var_names:
|
|
140
|
+
if var_name in data.var_names.keys():
|
|
141
|
+
processed_fields[var_name] = lateral_regrid.apply(
|
|
142
|
+
data.ds[data.var_names[var_name]]
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# rotation of velocities and interpolation to u/v points
|
|
146
|
+
if "u" in variable_info and "v" in variable_info:
|
|
147
|
+
(processed_fields["u"], processed_fields["v"],) = rotate_velocities(
|
|
148
|
+
processed_fields["u"],
|
|
149
|
+
processed_fields["v"],
|
|
150
|
+
target_coords["angle"],
|
|
151
|
+
interpolate=True,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# vertical regridding
|
|
155
|
+
for location in ["rho", "u", "v"]:
|
|
156
|
+
var_names = [
|
|
157
|
+
name
|
|
158
|
+
for name, info in variable_info.items()
|
|
159
|
+
if info["location"] == location and info["is_3d"]
|
|
160
|
+
]
|
|
161
|
+
if len(var_names) > 0:
|
|
162
|
+
vertical_regrid = VerticalRegrid(
|
|
163
|
+
self.grid.ds[f"layer_depth_{location}"],
|
|
164
|
+
data.ds[data.dim_names["depth"]],
|
|
165
|
+
)
|
|
166
|
+
for var_name in var_names:
|
|
167
|
+
if var_name in processed_fields:
|
|
168
|
+
processed_fields[var_name] = vertical_regrid.apply(
|
|
169
|
+
processed_fields[var_name]
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# compute barotropic velocities
|
|
173
|
+
if "u" in variable_info and "v" in variable_info:
|
|
174
|
+
for var_name in ["u", "v"]:
|
|
175
|
+
processed_fields[f"{var_name}bar"] = compute_barotropic_velocity(
|
|
176
|
+
processed_fields[var_name],
|
|
177
|
+
self.grid.ds[f"interface_depth_{var_name}"],
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
if type == "bgc":
|
|
181
|
+
# Ensure time coordinate matches that of physical variables
|
|
182
|
+
for var_name in variable_info.keys():
|
|
183
|
+
processed_fields[var_name] = processed_fields[var_name].assign_coords(
|
|
184
|
+
{"time": processed_fields["temp"]["time"]}
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
return processed_fields
|
|
188
|
+
|
|
140
189
|
def _input_checks(self):
|
|
141
190
|
|
|
142
191
|
if "name" not in self.source.keys():
|
|
@@ -201,19 +250,86 @@ class InitialConditions(ROMSToolsMixins):
|
|
|
201
250
|
|
|
202
251
|
return data
|
|
203
252
|
|
|
204
|
-
def
|
|
253
|
+
def _set_variable_info(self, data, type="physics"):
|
|
254
|
+
"""Sets up a dictionary with metadata for variables based on the type.
|
|
255
|
+
|
|
256
|
+
The dictionary contains the following information:
|
|
257
|
+
- `location`: Where the variable resides in the grid (e.g., rho, u, or v points).
|
|
258
|
+
- `is_vector`: Whether the variable is part of a vector (True for velocity components like 'u' and 'v').
|
|
259
|
+
- `vector_pair`: For vector variables, this indicates the associated variable that forms the vector (e.g., 'u' and 'v').
|
|
260
|
+
- `is_3d`: Indicates whether the variable is 3D (True for variables like 'temp' and 'salt') or 2D (False for 'zeta').
|
|
261
|
+
|
|
262
|
+
Returns
|
|
263
|
+
-------
|
|
264
|
+
dict
|
|
265
|
+
A dictionary where the keys are variable names and the values are dictionaries of metadata
|
|
266
|
+
about each variable, including 'location', 'is_vector', 'vector_pair', and 'is_3d'.
|
|
267
|
+
"""
|
|
268
|
+
default_info = {
|
|
269
|
+
"location": "rho",
|
|
270
|
+
"is_vector": False,
|
|
271
|
+
"vector_pair": None,
|
|
272
|
+
"is_3d": True,
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
# Define a dictionary for variable names and their associated information
|
|
276
|
+
if type == "physics":
|
|
277
|
+
variable_info = {
|
|
278
|
+
"zeta": {
|
|
279
|
+
"location": "rho",
|
|
280
|
+
"is_vector": False,
|
|
281
|
+
"vector_pair": None,
|
|
282
|
+
"is_3d": False,
|
|
283
|
+
},
|
|
284
|
+
"temp": default_info,
|
|
285
|
+
"salt": default_info,
|
|
286
|
+
"u": {
|
|
287
|
+
"location": "u",
|
|
288
|
+
"is_vector": True,
|
|
289
|
+
"vector_pair": "v",
|
|
290
|
+
"is_3d": True,
|
|
291
|
+
},
|
|
292
|
+
"v": {
|
|
293
|
+
"location": "v",
|
|
294
|
+
"is_vector": True,
|
|
295
|
+
"vector_pair": "u",
|
|
296
|
+
"is_3d": True,
|
|
297
|
+
},
|
|
298
|
+
"ubar": {
|
|
299
|
+
"location": "u",
|
|
300
|
+
"is_vector": True,
|
|
301
|
+
"vector_pair": "vbar",
|
|
302
|
+
"is_3d": False,
|
|
303
|
+
},
|
|
304
|
+
"vbar": {
|
|
305
|
+
"location": "v",
|
|
306
|
+
"is_vector": True,
|
|
307
|
+
"vector_pair": "ubar",
|
|
308
|
+
"is_3d": False,
|
|
309
|
+
},
|
|
310
|
+
}
|
|
311
|
+
elif type == "bgc":
|
|
312
|
+
variable_info = {}
|
|
313
|
+
for var_name in data.var_names.keys():
|
|
314
|
+
variable_info[var_name] = default_info
|
|
315
|
+
|
|
316
|
+
return variable_info
|
|
317
|
+
|
|
318
|
+
def _write_into_dataset(self, processed_fields, d_meta):
|
|
205
319
|
|
|
206
320
|
# save in new dataset
|
|
207
321
|
ds = xr.Dataset()
|
|
208
322
|
|
|
209
|
-
for
|
|
210
|
-
ds[
|
|
211
|
-
ds[
|
|
212
|
-
ds[
|
|
323
|
+
for var_name in processed_fields.keys():
|
|
324
|
+
ds[var_name] = processed_fields[var_name].astype(np.float32)
|
|
325
|
+
ds[var_name].attrs["long_name"] = d_meta[var_name]["long_name"]
|
|
326
|
+
ds[var_name].attrs["units"] = d_meta[var_name]["units"]
|
|
213
327
|
|
|
214
328
|
# initialize vertical velocity to zero
|
|
215
329
|
ds["w"] = xr.zeros_like(
|
|
216
|
-
self.grid.ds["interface_depth_rho"].expand_dims(
|
|
330
|
+
self.grid.ds["interface_depth_rho"].expand_dims(
|
|
331
|
+
time=processed_fields["u"].time
|
|
332
|
+
)
|
|
217
333
|
).astype(np.float32)
|
|
218
334
|
ds["w"].attrs["long_name"] = d_meta["w"]["long_name"]
|
|
219
335
|
ds["w"].attrs["units"] = d_meta["w"]["units"]
|
|
@@ -222,14 +338,18 @@ class InitialConditions(ROMSToolsMixins):
|
|
|
222
338
|
"s_rho",
|
|
223
339
|
"lat_rho",
|
|
224
340
|
"lon_rho",
|
|
225
|
-
"layer_depth_rho",
|
|
226
|
-
"interface_depth_rho",
|
|
227
341
|
"lat_u",
|
|
228
342
|
"lon_u",
|
|
229
343
|
"lat_v",
|
|
230
344
|
"lon_v",
|
|
345
|
+
"layer_depth_rho",
|
|
346
|
+
"interface_depth_rho",
|
|
347
|
+
"layer_depth_u",
|
|
348
|
+
"interface_depth_u",
|
|
349
|
+
"layer_depth_v",
|
|
350
|
+
"interface_depth_v",
|
|
231
351
|
]
|
|
232
|
-
existing_vars = [
|
|
352
|
+
existing_vars = [var_name for var_name in variables_to_drop if var_name in ds]
|
|
233
353
|
ds = ds.drop_vars(existing_vars)
|
|
234
354
|
|
|
235
355
|
ds["Cs_r"] = self.grid.ds["Cs_r"]
|
|
@@ -253,6 +373,29 @@ class InitialConditions(ROMSToolsMixins):
|
|
|
253
373
|
|
|
254
374
|
return ds
|
|
255
375
|
|
|
376
|
+
def _validate(self, ds):
|
|
377
|
+
"""Validates the dataset by checking for NaN values in SSH at wet points, which
|
|
378
|
+
would indicate missing raw data coverage over the target domain.
|
|
379
|
+
|
|
380
|
+
Parameters
|
|
381
|
+
----------
|
|
382
|
+
ds : xarray.Dataset
|
|
383
|
+
The dataset to validate.
|
|
384
|
+
|
|
385
|
+
Raises
|
|
386
|
+
------
|
|
387
|
+
ValueError
|
|
388
|
+
If NaN values are found in any of the specified variables at wet points,
|
|
389
|
+
indicating incomplete data coverage.
|
|
390
|
+
|
|
391
|
+
Notes
|
|
392
|
+
-----
|
|
393
|
+
This check is only applied to the 2D variable SSH to improve performance.
|
|
394
|
+
"""
|
|
395
|
+
|
|
396
|
+
ds["zeta"].load()
|
|
397
|
+
nan_check(ds["zeta"].squeeze(), self.grid.ds.mask_rho)
|
|
398
|
+
|
|
256
399
|
def _add_global_metadata(self, ds):
|
|
257
400
|
|
|
258
401
|
ds.attrs["title"] = "ROMS initial conditions file created by ROMS-Tools"
|
|
@@ -276,7 +419,7 @@ class InitialConditions(ROMSToolsMixins):
|
|
|
276
419
|
|
|
277
420
|
def plot(
|
|
278
421
|
self,
|
|
279
|
-
|
|
422
|
+
var_name,
|
|
280
423
|
s=None,
|
|
281
424
|
eta=None,
|
|
282
425
|
xi=None,
|
|
@@ -287,7 +430,7 @@ class InitialConditions(ROMSToolsMixins):
|
|
|
287
430
|
|
|
288
431
|
Parameters
|
|
289
432
|
----------
|
|
290
|
-
|
|
433
|
+
var_name : str
|
|
291
434
|
The name of the initial conditions field to plot. Options include:
|
|
292
435
|
|
|
293
436
|
- "temp": Potential temperature.
|
|
@@ -358,30 +501,30 @@ class InitialConditions(ROMSToolsMixins):
|
|
|
358
501
|
Raises
|
|
359
502
|
------
|
|
360
503
|
ValueError
|
|
361
|
-
If the specified `
|
|
362
|
-
If the field specified by `
|
|
363
|
-
If the field specified by `
|
|
504
|
+
If the specified `var_name` is not one of the valid options.
|
|
505
|
+
If the field specified by `var_name` is 3D and none of `s`, `eta`, or `xi` are specified.
|
|
506
|
+
If the field specified by `var_name` is 2D and both `eta` and `xi` are specified.
|
|
364
507
|
"""
|
|
365
508
|
|
|
366
|
-
if len(self.ds[
|
|
509
|
+
if len(self.ds[var_name].squeeze().dims) == 3 and not any(
|
|
367
510
|
[s is not None, eta is not None, xi is not None]
|
|
368
511
|
):
|
|
369
512
|
raise ValueError(
|
|
370
513
|
"For 3D fields, at least one of s, eta, or xi must be specified."
|
|
371
514
|
)
|
|
372
515
|
|
|
373
|
-
if len(self.ds[
|
|
516
|
+
if len(self.ds[var_name].squeeze().dims) == 2 and all(
|
|
374
517
|
[eta is not None, xi is not None]
|
|
375
518
|
):
|
|
376
519
|
raise ValueError("For 2D fields, specify either eta or xi, not both.")
|
|
377
520
|
|
|
378
|
-
self.ds[
|
|
379
|
-
field = self.ds[
|
|
521
|
+
self.ds[var_name].load()
|
|
522
|
+
field = self.ds[var_name].squeeze()
|
|
380
523
|
|
|
381
524
|
if all(dim in field.dims for dim in ["eta_rho", "xi_rho"]):
|
|
382
525
|
interface_depth = self.grid.ds.interface_depth_rho
|
|
383
526
|
layer_depth = self.grid.ds.layer_depth_rho
|
|
384
|
-
|
|
527
|
+
mask = self.grid.ds.mask_rho
|
|
385
528
|
field = field.assign_coords(
|
|
386
529
|
{"lon": self.grid.ds.lon_rho, "lat": self.grid.ds.lat_rho}
|
|
387
530
|
)
|
|
@@ -389,7 +532,7 @@ class InitialConditions(ROMSToolsMixins):
|
|
|
389
532
|
elif all(dim in field.dims for dim in ["eta_rho", "xi_u"]):
|
|
390
533
|
interface_depth = self.grid.ds.interface_depth_u
|
|
391
534
|
layer_depth = self.grid.ds.layer_depth_u
|
|
392
|
-
|
|
535
|
+
mask = self.grid.ds.mask_u
|
|
393
536
|
field = field.assign_coords(
|
|
394
537
|
{"lon": self.grid.ds.lon_u, "lat": self.grid.ds.lat_u}
|
|
395
538
|
)
|
|
@@ -397,7 +540,7 @@ class InitialConditions(ROMSToolsMixins):
|
|
|
397
540
|
elif all(dim in field.dims for dim in ["eta_v", "xi_rho"]):
|
|
398
541
|
interface_depth = self.grid.ds.interface_depth_v
|
|
399
542
|
layer_depth = self.grid.ds.layer_depth_v
|
|
400
|
-
|
|
543
|
+
mask = self.grid.ds.mask_v
|
|
401
544
|
field = field.assign_coords(
|
|
402
545
|
{"lon": self.grid.ds.lon_v, "lat": self.grid.ds.lat_v}
|
|
403
546
|
)
|
|
@@ -419,45 +562,49 @@ class InitialConditions(ROMSToolsMixins):
|
|
|
419
562
|
title = title + f", eta_rho = {field.eta_rho[eta].item()}"
|
|
420
563
|
field = field.isel(eta_rho=eta)
|
|
421
564
|
layer_depth = layer_depth.isel(eta_rho=eta)
|
|
422
|
-
field = field.assign_coords({"layer_depth": layer_depth})
|
|
423
565
|
interface_depth = interface_depth.isel(eta_rho=eta)
|
|
566
|
+
if "s_rho" in field.dims:
|
|
567
|
+
field = field.assign_coords({"layer_depth": layer_depth})
|
|
424
568
|
elif "eta_v" in field.dims:
|
|
425
569
|
title = title + f", eta_v = {field.eta_v[eta].item()}"
|
|
426
570
|
field = field.isel(eta_v=eta)
|
|
427
571
|
layer_depth = layer_depth.isel(eta_v=eta)
|
|
428
|
-
field = field.assign_coords({"layer_depth": layer_depth})
|
|
429
572
|
interface_depth = interface_depth.isel(eta_v=eta)
|
|
573
|
+
if "s_rho" in field.dims:
|
|
574
|
+
field = field.assign_coords({"layer_depth": layer_depth})
|
|
430
575
|
else:
|
|
431
576
|
raise ValueError(
|
|
432
|
-
f"None of the expected dimensions (eta_rho, eta_v) found in ds[{
|
|
577
|
+
f"None of the expected dimensions (eta_rho, eta_v) found in ds[{var_name}]."
|
|
433
578
|
)
|
|
434
579
|
if xi is not None:
|
|
435
580
|
if "xi_rho" in field.dims:
|
|
436
581
|
title = title + f", xi_rho = {field.xi_rho[xi].item()}"
|
|
437
582
|
field = field.isel(xi_rho=xi)
|
|
438
583
|
layer_depth = layer_depth.isel(xi_rho=xi)
|
|
439
|
-
field = field.assign_coords({"layer_depth": layer_depth})
|
|
440
584
|
interface_depth = interface_depth.isel(xi_rho=xi)
|
|
585
|
+
if "s_rho" in field.dims:
|
|
586
|
+
field = field.assign_coords({"layer_depth": layer_depth})
|
|
441
587
|
elif "xi_u" in field.dims:
|
|
442
588
|
title = title + f", xi_u = {field.xi_u[xi].item()}"
|
|
443
589
|
field = field.isel(xi_u=xi)
|
|
444
590
|
layer_depth = layer_depth.isel(xi_u=xi)
|
|
445
|
-
field = field.assign_coords({"layer_depth": layer_depth})
|
|
446
591
|
interface_depth = interface_depth.isel(xi_u=xi)
|
|
592
|
+
if "s_rho" in field.dims:
|
|
593
|
+
field = field.assign_coords({"layer_depth": layer_depth})
|
|
447
594
|
else:
|
|
448
595
|
raise ValueError(
|
|
449
|
-
f"None of the expected dimensions (xi_rho, xi_u) found in ds[{
|
|
596
|
+
f"None of the expected dimensions (xi_rho, xi_u) found in ds[{var_name}]."
|
|
450
597
|
)
|
|
451
598
|
|
|
452
599
|
# chose colorbar
|
|
453
|
-
if
|
|
600
|
+
if var_name in ["u", "v", "w", "ubar", "vbar", "zeta"]:
|
|
454
601
|
vmax = max(field.max().values, -field.min().values)
|
|
455
602
|
vmin = -vmax
|
|
456
603
|
cmap = plt.colormaps.get_cmap("RdBu_r")
|
|
457
604
|
else:
|
|
458
605
|
vmax = field.max().values
|
|
459
606
|
vmin = field.min().values
|
|
460
|
-
if
|
|
607
|
+
if var_name in ["temp", "salt"]:
|
|
461
608
|
cmap = plt.colormaps.get_cmap("YlOrRd")
|
|
462
609
|
else:
|
|
463
610
|
cmap = plt.colormaps.get_cmap("YlGn")
|
|
@@ -467,7 +614,7 @@ class InitialConditions(ROMSToolsMixins):
|
|
|
467
614
|
if eta is None and xi is None:
|
|
468
615
|
_plot(
|
|
469
616
|
self.grid.ds,
|
|
470
|
-
field=field,
|
|
617
|
+
field=field.where(mask),
|
|
471
618
|
straddle=self.grid.straddle,
|
|
472
619
|
depth_contours=depth_contours,
|
|
473
620
|
title=title,
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import xarray as xr
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class LateralRegrid:
|
|
5
|
+
"""Handles lateral regridding of data onto a new spatial grid."""
|
|
6
|
+
|
|
7
|
+
def __init__(self, target_coords, source_dim_names):
|
|
8
|
+
"""Initialize target grid coordinates and names for grid dimensions.
|
|
9
|
+
|
|
10
|
+
Parameters
|
|
11
|
+
----------
|
|
12
|
+
target_coords : dict
|
|
13
|
+
Dictionary containing 'lon' and 'lat' as xarray.DataArrays representing
|
|
14
|
+
the longitude and latitude values of the target grid.
|
|
15
|
+
source_dim_names : dict
|
|
16
|
+
Dictionary specifying names for the latitude and longitude dimensions,
|
|
17
|
+
typically using keys like "latitude" and "longitude" to align with the dataset conventions.
|
|
18
|
+
|
|
19
|
+
Attributes
|
|
20
|
+
----------
|
|
21
|
+
coords : dict
|
|
22
|
+
Maps the dimension names to the corresponding latitude and longitude
|
|
23
|
+
DataArrays, providing easy access to target grid coordinates.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
self.coords = {
|
|
27
|
+
source_dim_names["latitude"]: target_coords["lat"],
|
|
28
|
+
source_dim_names["longitude"]: target_coords["lon"],
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
def apply(self, da):
|
|
32
|
+
"""Fills missing values and regrids the variable.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
da : xarray.DataArray
|
|
37
|
+
Input data to fill and regrid.
|
|
38
|
+
|
|
39
|
+
Returns
|
|
40
|
+
-------
|
|
41
|
+
xarray.DataArray
|
|
42
|
+
Regridded data with filled values.
|
|
43
|
+
"""
|
|
44
|
+
regridded = da.interp(self.coords, method="linear").drop_vars(
|
|
45
|
+
list(self.coords.keys())
|
|
46
|
+
)
|
|
47
|
+
return regridded
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class VerticalRegrid:
|
|
51
|
+
"""Interpolates data onto new vertical (depth) coordinates.
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
----------
|
|
55
|
+
target_depth_coords : xarray.DataArray
|
|
56
|
+
Depth coordinates for the target grid.
|
|
57
|
+
source_depth_coords : xarray.DataArray
|
|
58
|
+
Depth coordinates for the source grid.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def __init__(self, target_depth_coords, source_depth_coords):
|
|
62
|
+
"""Initialize regridding factors for interpolation.
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
target_depth_coords : xarray.DataArray
|
|
67
|
+
Depth coordinates for the target grid.
|
|
68
|
+
source_depth_coords : xarray.DataArray
|
|
69
|
+
Depth coordinates for the source grid.
|
|
70
|
+
|
|
71
|
+
Attributes
|
|
72
|
+
----------
|
|
73
|
+
coeff : xarray.Dataset
|
|
74
|
+
Dataset containing:
|
|
75
|
+
- `is_below` : Boolean mask for depths just below target.
|
|
76
|
+
- `is_above` : Boolean mask for depths just above target.
|
|
77
|
+
- `upper_mask`, `lower_mask` : Masks for valid interpolation bounds.
|
|
78
|
+
- `factor` : Weight for blending values between levels.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
self.depth_dim = source_depth_coords.dims[0]
|
|
82
|
+
source_depth = source_depth_coords
|
|
83
|
+
dims = {"dim": self.depth_dim}
|
|
84
|
+
|
|
85
|
+
dlev = source_depth - target_depth_coords
|
|
86
|
+
is_below = dlev == dlev.where(dlev >= 0).min(**dims)
|
|
87
|
+
is_above = dlev == dlev.where(dlev <= 0).max(**dims)
|
|
88
|
+
p_below = dlev.where(is_below).sum(**dims)
|
|
89
|
+
p_above = -dlev.where(is_above).sum(**dims)
|
|
90
|
+
denominator = p_below + p_above
|
|
91
|
+
denominator = denominator.where(denominator > 1e-6, 1e-6)
|
|
92
|
+
factor = p_below / denominator
|
|
93
|
+
|
|
94
|
+
upper_mask = is_above.sum(**dims) > 0
|
|
95
|
+
lower_mask = is_below.sum(**dims) > 0
|
|
96
|
+
|
|
97
|
+
self.coeff = xr.Dataset(
|
|
98
|
+
{
|
|
99
|
+
"is_below": is_below,
|
|
100
|
+
"is_above": is_above,
|
|
101
|
+
"upper_mask": upper_mask,
|
|
102
|
+
"lower_mask": lower_mask,
|
|
103
|
+
"factor": factor,
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
def apply(self, var, fill_nans=True):
|
|
108
|
+
"""Interpolates the variable onto the new depth grid using precomputed
|
|
109
|
+
coefficients for linear interpolation between layers.
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
var : xarray.DataArray
|
|
114
|
+
The input data to be regridded along the depth dimension. This should be
|
|
115
|
+
an array with the same depth coordinates as the original grid.
|
|
116
|
+
fill_nans : bool, optional
|
|
117
|
+
Whether to fill NaN values in the regridded data. If True (default),
|
|
118
|
+
forward-fill and backward-fill are applied along the 's_rho' dimension to
|
|
119
|
+
ensure there are no NaNs after interpolation.
|
|
120
|
+
|
|
121
|
+
Returns
|
|
122
|
+
-------
|
|
123
|
+
xarray.DataArray
|
|
124
|
+
The regridded data array, interpolated onto the new depth grid. NaN values
|
|
125
|
+
are replaced if `fill_nans=True`, with extrapolation allowed at the surface
|
|
126
|
+
and bottom layers to minimize gaps.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
dims = {"dim": self.depth_dim}
|
|
130
|
+
|
|
131
|
+
var_below = var.where(self.coeff["is_below"]).sum(**dims)
|
|
132
|
+
var_above = var.where(self.coeff["is_above"]).sum(**dims)
|
|
133
|
+
|
|
134
|
+
result = var_below + (var_above - var_below) * self.coeff["factor"]
|
|
135
|
+
if fill_nans:
|
|
136
|
+
result = result.where(self.coeff["upper_mask"], var.isel({dims["dim"]: 0}))
|
|
137
|
+
result = result.where(self.coeff["lower_mask"], var.isel({dims["dim"]: -1}))
|
|
138
|
+
else:
|
|
139
|
+
result = result.where(self.coeff["upper_mask"]).where(
|
|
140
|
+
self.coeff["lower_mask"]
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
return result
|