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
|
@@ -7,7 +7,7 @@ from roms_tools.setup.grid import Grid
|
|
|
7
7
|
from datetime import datetime
|
|
8
8
|
import numpy as np
|
|
9
9
|
from typing import Dict, Union, List
|
|
10
|
-
from roms_tools.setup.
|
|
10
|
+
from roms_tools.setup.regrid import LateralRegrid
|
|
11
11
|
from roms_tools.setup.datasets import (
|
|
12
12
|
ERA5Dataset,
|
|
13
13
|
ERA5Correction,
|
|
@@ -20,6 +20,8 @@ from roms_tools.setup.utils import (
|
|
|
20
20
|
get_variable_metadata,
|
|
21
21
|
group_dataset,
|
|
22
22
|
save_datasets,
|
|
23
|
+
get_target_coords,
|
|
24
|
+
rotate_velocities,
|
|
23
25
|
)
|
|
24
26
|
from roms_tools.setup.plot import _plot
|
|
25
27
|
import matplotlib.pyplot as plt
|
|
@@ -27,7 +29,7 @@ from pathlib import Path
|
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
@dataclass(frozen=True, kw_only=True)
|
|
30
|
-
class SurfaceForcing
|
|
32
|
+
class SurfaceForcing:
|
|
31
33
|
"""Represents surface forcing input data for ROMS.
|
|
32
34
|
|
|
33
35
|
Parameters
|
|
@@ -91,69 +93,45 @@ class SurfaceForcing(ROMSToolsMixins):
|
|
|
91
93
|
def __post_init__(self):
|
|
92
94
|
|
|
93
95
|
self._input_checks()
|
|
94
|
-
|
|
95
|
-
object.__setattr__(self, "
|
|
96
|
-
object.__setattr__(self, "target_lat", lat)
|
|
96
|
+
target_coords = get_target_coords(self.grid, self.use_coarse_grid)
|
|
97
|
+
object.__setattr__(self, "target_coords", target_coords)
|
|
97
98
|
|
|
98
99
|
data = self._get_data()
|
|
99
100
|
data.choose_subdomain(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
margin=2,
|
|
103
|
-
straddle=straddle,
|
|
101
|
+
target_coords,
|
|
102
|
+
buffer_points=20, # lateral fill needs some buffer from data margin
|
|
104
103
|
)
|
|
105
|
-
if self.type == "physics":
|
|
106
|
-
vars_2d = ["uwnd", "vwnd", "swrad", "lwrad", "Tair", "qair", "rain"]
|
|
107
|
-
elif self.type == "bgc":
|
|
108
|
-
vars_2d = data.var_names.keys()
|
|
109
|
-
vars_3d = []
|
|
110
104
|
|
|
111
|
-
|
|
105
|
+
data.apply_lateral_fill()
|
|
112
106
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
],
|
|
124
|
-
correction_data.dim_names["longitude"]: data.ds[
|
|
125
|
-
data.dim_names["longitude"]
|
|
126
|
-
],
|
|
127
|
-
}
|
|
128
|
-
correction_data.choose_subdomain(coords_correction, straddle=straddle)
|
|
129
|
-
# apply mask from ERA5 data
|
|
130
|
-
if "mask" in data.var_names.keys():
|
|
131
|
-
mask = data.ds["mask"]
|
|
132
|
-
for var in correction_data.ds.data_vars:
|
|
133
|
-
correction_data.ds[var] = xr.where(
|
|
134
|
-
mask == 1, correction_data.ds[var], np.nan
|
|
135
|
-
)
|
|
136
|
-
correction_data.ds["mask"] = mask
|
|
137
|
-
vars_2d = ["swr_corr"]
|
|
138
|
-
vars_3d = []
|
|
139
|
-
# spatial interpolation
|
|
140
|
-
data_vars_corr = super()._regrid_data(
|
|
141
|
-
correction_data, vars_2d, vars_3d, lon, lat
|
|
142
|
-
)
|
|
143
|
-
# temporal interpolation
|
|
144
|
-
corr_factor = interpolate_from_climatology(
|
|
145
|
-
data_vars_corr["swr_corr"],
|
|
146
|
-
correction_data.dim_names["time"],
|
|
147
|
-
time=data_vars["swrad"].time,
|
|
107
|
+
variable_info = self._set_variable_info(data)
|
|
108
|
+
var_names = variable_info.keys()
|
|
109
|
+
|
|
110
|
+
processed_fields = {}
|
|
111
|
+
# lateral regridding
|
|
112
|
+
lateral_regrid = LateralRegrid(target_coords, data.dim_names)
|
|
113
|
+
for var_name in var_names:
|
|
114
|
+
if var_name in data.var_names.keys():
|
|
115
|
+
processed_fields[var_name] = lateral_regrid.apply(
|
|
116
|
+
data.ds[data.var_names[var_name]]
|
|
148
117
|
)
|
|
149
118
|
|
|
150
|
-
|
|
119
|
+
# rotation of velocities and interpolation to u/v points
|
|
120
|
+
if "uwnd" in variable_info and "vwnd" in variable_info:
|
|
121
|
+
processed_fields["uwnd"], processed_fields["vwnd"] = rotate_velocities(
|
|
122
|
+
processed_fields["uwnd"],
|
|
123
|
+
processed_fields["vwnd"],
|
|
124
|
+
target_coords["angle"],
|
|
125
|
+
interpolate=False,
|
|
126
|
+
)
|
|
151
127
|
|
|
152
|
-
|
|
128
|
+
# correct radiation
|
|
129
|
+
if self.type == "physics" and self.correct_radiation:
|
|
130
|
+
processed_fields = self._apply_correction(processed_fields, data)
|
|
153
131
|
|
|
154
132
|
d_meta = get_variable_metadata()
|
|
155
133
|
|
|
156
|
-
ds = self._write_into_dataset(data, d_meta)
|
|
134
|
+
ds = self._write_into_dataset(processed_fields, data, d_meta)
|
|
157
135
|
|
|
158
136
|
if self.use_coarse_grid:
|
|
159
137
|
mask = self.grid.ds["mask_coarse"].rename(
|
|
@@ -162,13 +140,11 @@ class SurfaceForcing(ROMSToolsMixins):
|
|
|
162
140
|
else:
|
|
163
141
|
mask = self.grid.ds["mask_rho"]
|
|
164
142
|
|
|
165
|
-
|
|
166
|
-
for var in ds.data_vars:
|
|
167
|
-
nan_check(ds[var].isel(time=0), mask)
|
|
143
|
+
self._validate(ds, mask)
|
|
168
144
|
|
|
169
145
|
# substitute NaNs over land by a fill value to avoid blow-up of ROMS
|
|
170
|
-
for
|
|
171
|
-
ds[
|
|
146
|
+
for var_name in ds.data_vars:
|
|
147
|
+
ds[var_name] = substitute_nans_by_fillvalue(ds[var_name])
|
|
172
148
|
|
|
173
149
|
object.__setattr__(self, "ds", ds)
|
|
174
150
|
|
|
@@ -231,15 +207,98 @@ class SurfaceForcing(ROMSToolsMixins):
|
|
|
231
207
|
|
|
232
208
|
return correction_data
|
|
233
209
|
|
|
234
|
-
def
|
|
210
|
+
def _set_variable_info(self, data):
|
|
211
|
+
"""Sets up a dictionary with metadata for variables based on the type of data
|
|
212
|
+
(physics or BGC).
|
|
213
|
+
|
|
214
|
+
The dictionary contains the following information:
|
|
215
|
+
- `location`: Where the variable resides in the grid (e.g., rho, u, or v points).
|
|
216
|
+
- `is_vector`: Whether the variable is part of a vector (True for velocity components like 'u' and 'v').
|
|
217
|
+
- `vector_pair`: For vector variables, this indicates the associated variable that forms the vector (e.g., 'u' and 'v').
|
|
218
|
+
- `is_3d`: Indicates whether the variable is 3D (True for variables like 'temp' and 'salt') or 2D (False for 'zeta').
|
|
219
|
+
|
|
220
|
+
Returns
|
|
221
|
+
-------
|
|
222
|
+
dict
|
|
223
|
+
A dictionary where the keys are variable names and the values are dictionaries of metadata
|
|
224
|
+
about each variable, including 'location', 'is_vector', 'vector_pair', and 'is_3d'.
|
|
225
|
+
"""
|
|
226
|
+
default_info = {
|
|
227
|
+
"location": "rho",
|
|
228
|
+
"is_vector": False,
|
|
229
|
+
"vector_pair": None,
|
|
230
|
+
"is_3d": False,
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
# Define a dictionary for variable names and their associated information
|
|
234
|
+
if self.type == "physics":
|
|
235
|
+
variable_info = {
|
|
236
|
+
"swrad": default_info,
|
|
237
|
+
"lwrad": default_info,
|
|
238
|
+
"Tair": default_info,
|
|
239
|
+
"qair": default_info,
|
|
240
|
+
"rain": default_info,
|
|
241
|
+
"uwnd": {
|
|
242
|
+
"location": "u",
|
|
243
|
+
"is_vector": True,
|
|
244
|
+
"vector_pair": "vwnd",
|
|
245
|
+
"is_3d": False,
|
|
246
|
+
},
|
|
247
|
+
"vwnd": {
|
|
248
|
+
"location": "v",
|
|
249
|
+
"is_vector": True,
|
|
250
|
+
"vector_pair": "uwnd",
|
|
251
|
+
"is_3d": False,
|
|
252
|
+
},
|
|
253
|
+
}
|
|
254
|
+
elif self.type == "bgc":
|
|
255
|
+
variable_info = {}
|
|
256
|
+
for var in data.var_names.keys():
|
|
257
|
+
variable_info[var] = default_info
|
|
258
|
+
|
|
259
|
+
return variable_info
|
|
260
|
+
|
|
261
|
+
def _apply_correction(self, processed_fields, data):
|
|
262
|
+
|
|
263
|
+
correction_data = self._get_correction_data()
|
|
264
|
+
# choose same subdomain as forcing data so that we can use same mask
|
|
265
|
+
coords_correction = {
|
|
266
|
+
correction_data.dim_names["latitude"]: data.ds[data.dim_names["latitude"]],
|
|
267
|
+
correction_data.dim_names["longitude"]: data.ds[
|
|
268
|
+
data.dim_names["longitude"]
|
|
269
|
+
],
|
|
270
|
+
}
|
|
271
|
+
correction_data.choose_subdomain(
|
|
272
|
+
coords_correction, straddle=self.target_coords["straddle"]
|
|
273
|
+
)
|
|
274
|
+
correction_data.ds["mask"] = data.ds["mask"] # use mask from ERA5 data
|
|
275
|
+
correction_data.apply_lateral_fill()
|
|
276
|
+
# regrid
|
|
277
|
+
lateral_regrid = LateralRegrid(self.target_coords, correction_data.dim_names)
|
|
278
|
+
corr_factor = lateral_regrid.apply(
|
|
279
|
+
correction_data.ds[correction_data.var_names["swr_corr"]]
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
# temporal interpolation
|
|
283
|
+
corr_factor = interpolate_from_climatology(
|
|
284
|
+
corr_factor,
|
|
285
|
+
correction_data.dim_names["time"],
|
|
286
|
+
time=processed_fields["swrad"].time,
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
processed_fields["swrad"] = processed_fields["swrad"] * corr_factor
|
|
290
|
+
|
|
291
|
+
return processed_fields
|
|
292
|
+
|
|
293
|
+
def _write_into_dataset(self, processed_fields, data, d_meta):
|
|
235
294
|
|
|
236
295
|
# save in new dataset
|
|
237
296
|
ds = xr.Dataset()
|
|
238
297
|
|
|
239
|
-
for
|
|
240
|
-
ds[
|
|
241
|
-
ds[
|
|
242
|
-
ds[
|
|
298
|
+
for var_name in processed_fields.keys():
|
|
299
|
+
ds[var_name] = processed_fields[var_name].astype(np.float32)
|
|
300
|
+
ds[var_name].attrs["long_name"] = d_meta[var_name]["long_name"]
|
|
301
|
+
ds[var_name].attrs["units"] = d_meta[var_name]["units"]
|
|
243
302
|
|
|
244
303
|
if self.use_coarse_grid:
|
|
245
304
|
ds = ds.rename({"eta_coarse": "eta_rho", "xi_coarse": "xi_rho"})
|
|
@@ -305,11 +364,36 @@ class SurfaceForcing(ROMSToolsMixins):
|
|
|
305
364
|
ds = ds.drop_vars(["time"])
|
|
306
365
|
|
|
307
366
|
variables_to_drop = ["lat_rho", "lon_rho", "lat_coarse", "lon_coarse"]
|
|
308
|
-
existing_vars = [
|
|
367
|
+
existing_vars = [var_name for var_name in variables_to_drop if var_name in ds]
|
|
309
368
|
ds = ds.drop_vars(existing_vars)
|
|
310
369
|
|
|
311
370
|
return ds
|
|
312
371
|
|
|
372
|
+
def _validate(self, ds, mask):
|
|
373
|
+
"""Validates the dataset by checking for NaN values at wet points, which would
|
|
374
|
+
indicate missing raw data coverage over the target domain.
|
|
375
|
+
|
|
376
|
+
Parameters
|
|
377
|
+
----------
|
|
378
|
+
ds : xarray.Dataset
|
|
379
|
+
The dataset to validate.
|
|
380
|
+
mask : xarray.DataArray
|
|
381
|
+
Land mask (1=ocean, 0=land) to determine wet points in the domain.
|
|
382
|
+
|
|
383
|
+
Raises
|
|
384
|
+
------
|
|
385
|
+
ValueError
|
|
386
|
+
If NaN values are found in any of the specified variables at wet points,
|
|
387
|
+
indicating incomplete data coverage.
|
|
388
|
+
|
|
389
|
+
Notes
|
|
390
|
+
-----
|
|
391
|
+
This check is applied to the first time step (`time=0`) of each variable in the provided dataset.
|
|
392
|
+
"""
|
|
393
|
+
|
|
394
|
+
for var_name in ds.data_vars:
|
|
395
|
+
nan_check(ds[var_name].isel(time=0), mask)
|
|
396
|
+
|
|
313
397
|
def _add_global_metadata(self, ds=None):
|
|
314
398
|
|
|
315
399
|
if ds is None:
|
|
@@ -333,12 +417,12 @@ class SurfaceForcing(ROMSToolsMixins):
|
|
|
333
417
|
|
|
334
418
|
return ds
|
|
335
419
|
|
|
336
|
-
def plot(self,
|
|
420
|
+
def plot(self, var_name, time=0) -> None:
|
|
337
421
|
"""Plot the specified surface forcing field for a given time slice.
|
|
338
422
|
|
|
339
423
|
Parameters
|
|
340
424
|
----------
|
|
341
|
-
|
|
425
|
+
var_name : str
|
|
342
426
|
The name of the surface forcing field to plot. Options include:
|
|
343
427
|
|
|
344
428
|
- "uwnd": 10 meter wind in x-direction.
|
|
@@ -367,7 +451,7 @@ class SurfaceForcing(ROMSToolsMixins):
|
|
|
367
451
|
Raises
|
|
368
452
|
------
|
|
369
453
|
ValueError
|
|
370
|
-
If the specified
|
|
454
|
+
If the specified var_name is not found in dataset.
|
|
371
455
|
|
|
372
456
|
|
|
373
457
|
Examples
|
|
@@ -375,10 +459,10 @@ class SurfaceForcing(ROMSToolsMixins):
|
|
|
375
459
|
>>> atm_forcing.plot("uwnd", time=0)
|
|
376
460
|
"""
|
|
377
461
|
|
|
378
|
-
if
|
|
379
|
-
raise ValueError(f"Variable '{
|
|
462
|
+
if var_name not in self.ds:
|
|
463
|
+
raise ValueError(f"Variable '{var_name}' is not found in dataset.")
|
|
380
464
|
|
|
381
|
-
field = self.ds[
|
|
465
|
+
field = self.ds[var_name].isel(time=time).load()
|
|
382
466
|
title = field.long_name
|
|
383
467
|
|
|
384
468
|
# assign lat / lon
|
|
@@ -388,17 +472,19 @@ class SurfaceForcing(ROMSToolsMixins):
|
|
|
388
472
|
else:
|
|
389
473
|
field = field.where(self.grid.ds.mask_rho)
|
|
390
474
|
|
|
391
|
-
field = field.assign_coords(
|
|
475
|
+
field = field.assign_coords(
|
|
476
|
+
{"lon": self.target_coords["lon"], "lat": self.target_coords["lat"]}
|
|
477
|
+
)
|
|
392
478
|
|
|
393
479
|
# choose colorbar
|
|
394
|
-
if
|
|
480
|
+
if var_name in ["uwnd", "vwnd"]:
|
|
395
481
|
vmax = max(field.max().values, -field.min().values)
|
|
396
482
|
vmin = -vmax
|
|
397
483
|
cmap = plt.colormaps.get_cmap("RdBu_r")
|
|
398
484
|
else:
|
|
399
485
|
vmax = field.max().values
|
|
400
486
|
vmin = field.min().values
|
|
401
|
-
if
|
|
487
|
+
if var_name in ["swrad", "lwrad", "Tair", "qair"]:
|
|
402
488
|
cmap = plt.colormaps.get_cmap("YlOrRd")
|
|
403
489
|
else:
|
|
404
490
|
cmap = plt.colormaps.get_cmap("YlGnBu")
|
roms_tools/setup/tides.py
CHANGED
|
@@ -16,15 +16,18 @@ from roms_tools.setup.utils import (
|
|
|
16
16
|
interpolate_from_rho_to_v,
|
|
17
17
|
get_variable_metadata,
|
|
18
18
|
save_datasets,
|
|
19
|
+
get_target_coords,
|
|
20
|
+
rotate_velocities,
|
|
21
|
+
get_vector_pairs,
|
|
19
22
|
)
|
|
20
|
-
from roms_tools.setup.
|
|
23
|
+
from roms_tools.setup.regrid import LateralRegrid
|
|
21
24
|
import matplotlib.pyplot as plt
|
|
22
25
|
from pathlib import Path
|
|
23
26
|
|
|
24
27
|
|
|
25
28
|
@dataclass(frozen=True, kw_only=True)
|
|
26
|
-
class TidalForcing
|
|
27
|
-
"""Represents tidal forcing
|
|
29
|
+
class TidalForcing:
|
|
30
|
+
"""Represents tidal forcing for ROMS.
|
|
28
31
|
|
|
29
32
|
Parameters
|
|
30
33
|
----------
|
|
@@ -68,67 +71,69 @@ class TidalForcing(ROMSToolsMixins):
|
|
|
68
71
|
def __post_init__(self):
|
|
69
72
|
|
|
70
73
|
self._input_checks()
|
|
71
|
-
|
|
74
|
+
target_coords = get_target_coords(self.grid)
|
|
72
75
|
|
|
73
76
|
data = self._get_data()
|
|
74
|
-
|
|
75
77
|
data.check_number_constituents(self.ntides)
|
|
76
78
|
data.choose_subdomain(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
margin=2,
|
|
80
|
-
straddle=straddle,
|
|
79
|
+
target_coords,
|
|
80
|
+
buffer_points=20,
|
|
81
81
|
)
|
|
82
|
-
|
|
83
82
|
# select desired number of constituents
|
|
84
83
|
object.__setattr__(data, "ds", data.ds.isel(ntides=slice(None, self.ntides)))
|
|
85
|
-
|
|
86
84
|
self._correct_tides(data)
|
|
87
85
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
86
|
+
data.apply_lateral_fill()
|
|
87
|
+
|
|
88
|
+
variable_info = self._set_variable_info()
|
|
89
|
+
var_names = variable_info.keys()
|
|
90
|
+
|
|
91
|
+
processed_fields = {}
|
|
92
|
+
# lateral regridding
|
|
93
|
+
lateral_regrid = LateralRegrid(target_coords, data.dim_names)
|
|
94
|
+
for var_name in var_names:
|
|
95
|
+
if var_name in data.var_names.keys():
|
|
96
|
+
processed_fields[var_name] = lateral_regrid.apply(
|
|
97
|
+
data.ds[data.var_names[var_name]]
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# rotation of velocities and interpolation to u/v points
|
|
101
|
+
vector_pairs = get_vector_pairs(variable_info)
|
|
102
|
+
for pair in vector_pairs:
|
|
103
|
+
u_component = pair[0]
|
|
104
|
+
v_component = pair[1]
|
|
105
|
+
if u_component in processed_fields and v_component in processed_fields:
|
|
106
|
+
(
|
|
107
|
+
processed_fields[u_component],
|
|
108
|
+
processed_fields[v_component],
|
|
109
|
+
) = rotate_velocities(
|
|
110
|
+
processed_fields[u_component],
|
|
111
|
+
processed_fields[v_component],
|
|
112
|
+
target_coords["angle"],
|
|
113
|
+
interpolate=False,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# convert to barotropic velocity
|
|
117
|
+
for var_name in ["u_Re", "v_Re", "u_Im", "v_Im"]:
|
|
118
|
+
processed_fields[var_name] = processed_fields[var_name] / self.grid.ds.h
|
|
119
|
+
|
|
120
|
+
# interpolate from rho- to velocity points
|
|
114
121
|
for uname in ["u_Re", "u_Im"]:
|
|
115
|
-
|
|
122
|
+
processed_fields[uname] = interpolate_from_rho_to_u(processed_fields[uname])
|
|
116
123
|
for vname in ["v_Re", "v_Im"]:
|
|
117
|
-
|
|
124
|
+
processed_fields[vname] = interpolate_from_rho_to_v(processed_fields[vname])
|
|
118
125
|
|
|
119
126
|
d_meta = get_variable_metadata()
|
|
120
|
-
ds = self._write_into_dataset(
|
|
127
|
+
ds = self._write_into_dataset(processed_fields, d_meta)
|
|
121
128
|
ds["omega"] = data.ds["omega"]
|
|
122
129
|
|
|
123
130
|
ds = self._add_global_metadata(ds)
|
|
124
131
|
|
|
125
|
-
|
|
126
|
-
for var in ["ssh_Re", "u_Re", "v_Im"]:
|
|
127
|
-
nan_check(ds[var].isel(ntides=0), self.grid.ds.mask_rho)
|
|
132
|
+
self._validate(ds)
|
|
128
133
|
|
|
129
134
|
# substitute NaNs over land by a fill value to avoid blow-up of ROMS
|
|
130
|
-
for
|
|
131
|
-
ds[
|
|
135
|
+
for var_name in ds.data_vars:
|
|
136
|
+
ds[var_name] = substitute_nans_by_fillvalue(ds[var_name])
|
|
132
137
|
|
|
133
138
|
object.__setattr__(self, "ds", ds)
|
|
134
139
|
|
|
@@ -147,15 +152,71 @@ class TidalForcing(ROMSToolsMixins):
|
|
|
147
152
|
raise ValueError('Only "TPXO" is a valid option for source["name"].')
|
|
148
153
|
return data
|
|
149
154
|
|
|
150
|
-
def
|
|
155
|
+
def _set_variable_info(self):
|
|
156
|
+
"""Sets up a dictionary with metadata for variables based on the type.
|
|
157
|
+
|
|
158
|
+
The dictionary contains the following information:
|
|
159
|
+
- `location`: Where the variable resides in the grid (e.g., rho, u, or v points).
|
|
160
|
+
- `is_vector`: Whether the variable is part of a vector (True for velocity components like 'u' and 'v').
|
|
161
|
+
- `vector_pair`: For vector variables, this indicates the associated variable that forms the vector (e.g., 'u' and 'v').
|
|
162
|
+
- `is_3d`: Indicates whether the variable is 3D (True for variables like 'temp' and 'salt') or 2D (False for 'zeta').
|
|
163
|
+
|
|
164
|
+
Returns
|
|
165
|
+
-------
|
|
166
|
+
dict
|
|
167
|
+
A dictionary where the keys are variable names and the values are dictionaries of metadata
|
|
168
|
+
about each variable, including 'location', 'is_vector', 'vector_pair', and 'is_3d'.
|
|
169
|
+
"""
|
|
170
|
+
default_info = {
|
|
171
|
+
"location": "rho",
|
|
172
|
+
"is_vector": False,
|
|
173
|
+
"vector_pair": None,
|
|
174
|
+
"is_3d": False,
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
# Define a dictionary for variable names and their associated information
|
|
178
|
+
variable_info = {
|
|
179
|
+
"ssh_Re": default_info,
|
|
180
|
+
"ssh_Im": default_info,
|
|
181
|
+
"pot_Re": default_info,
|
|
182
|
+
"pot_Im": default_info,
|
|
183
|
+
"u_Re": {
|
|
184
|
+
"location": "u",
|
|
185
|
+
"is_vector": True,
|
|
186
|
+
"vector_pair": "v_Re",
|
|
187
|
+
"is_3d": False,
|
|
188
|
+
},
|
|
189
|
+
"v_Re": {
|
|
190
|
+
"location": "v",
|
|
191
|
+
"is_vector": True,
|
|
192
|
+
"vector_pair": "u_Re",
|
|
193
|
+
"is_3d": False,
|
|
194
|
+
},
|
|
195
|
+
"u_Im": {
|
|
196
|
+
"location": "u",
|
|
197
|
+
"is_vector": True,
|
|
198
|
+
"vector_pair": "v_Im",
|
|
199
|
+
"is_3d": False,
|
|
200
|
+
},
|
|
201
|
+
"v_Im": {
|
|
202
|
+
"location": "v",
|
|
203
|
+
"is_vector": True,
|
|
204
|
+
"vector_pair": "u_Im",
|
|
205
|
+
"is_3d": False,
|
|
206
|
+
},
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return variable_info
|
|
210
|
+
|
|
211
|
+
def _write_into_dataset(self, processed_fields, d_meta):
|
|
151
212
|
|
|
152
213
|
# save in new dataset
|
|
153
214
|
ds = xr.Dataset()
|
|
154
215
|
|
|
155
|
-
for
|
|
156
|
-
ds[
|
|
157
|
-
ds[
|
|
158
|
-
ds[
|
|
216
|
+
for var_name in processed_fields.keys():
|
|
217
|
+
ds[var_name] = processed_fields[var_name].astype(np.float32)
|
|
218
|
+
ds[var_name].attrs["long_name"] = d_meta[var_name]["long_name"]
|
|
219
|
+
ds[var_name].attrs["units"] = d_meta[var_name]["units"]
|
|
159
220
|
|
|
160
221
|
ds = ds.drop_vars(["lat_rho", "lon_rho"])
|
|
161
222
|
|
|
@@ -178,12 +239,35 @@ class TidalForcing(ROMSToolsMixins):
|
|
|
178
239
|
|
|
179
240
|
return ds
|
|
180
241
|
|
|
181
|
-
def
|
|
242
|
+
def _validate(self, ds):
|
|
243
|
+
"""Validates the dataset by checking for NaN values at wet points, which would
|
|
244
|
+
indicate missing raw data coverage over the target domain.
|
|
245
|
+
|
|
246
|
+
Parameters
|
|
247
|
+
----------
|
|
248
|
+
ds : xarray.Dataset
|
|
249
|
+
The dataset to validate, containing tidal variables and a mask for wet points.
|
|
250
|
+
|
|
251
|
+
Raises
|
|
252
|
+
------
|
|
253
|
+
ValueError
|
|
254
|
+
If NaN values are found in any of the specified variables at wet points,
|
|
255
|
+
indicating incomplete data coverage.
|
|
256
|
+
|
|
257
|
+
Notes
|
|
258
|
+
-----
|
|
259
|
+
This check is applied to the first constituent (`ntides=0`) of each variable in the dataset.
|
|
260
|
+
The method utilizes `self.grid.ds.mask_rho` to determine the wet points in the domain.
|
|
261
|
+
"""
|
|
262
|
+
for var_name in ds.data_vars:
|
|
263
|
+
nan_check(ds[var_name].isel(ntides=0), self.grid.ds.mask_rho)
|
|
264
|
+
|
|
265
|
+
def plot(self, var_name, ntides=0) -> None:
|
|
182
266
|
"""Plot the specified tidal forcing variable for a given tidal constituent.
|
|
183
267
|
|
|
184
268
|
Parameters
|
|
185
269
|
----------
|
|
186
|
-
|
|
270
|
+
var_name : str
|
|
187
271
|
The tidal forcing variable to plot. Options include:
|
|
188
272
|
|
|
189
273
|
- "ssh_Re": Real part of tidal elevation.
|
|
@@ -216,7 +300,7 @@ class TidalForcing(ROMSToolsMixins):
|
|
|
216
300
|
>>> tidal_forcing.plot("ssh_Re", nc=0)
|
|
217
301
|
"""
|
|
218
302
|
|
|
219
|
-
field = self.ds[
|
|
303
|
+
field = self.ds[var_name].isel(ntides=ntides).compute()
|
|
220
304
|
if all(dim in field.dims for dim in ["eta_rho", "xi_rho"]):
|
|
221
305
|
field = field.where(self.grid.ds.mask_rho)
|
|
222
306
|
field = field.assign_coords(
|
|
@@ -237,7 +321,7 @@ class TidalForcing(ROMSToolsMixins):
|
|
|
237
321
|
else:
|
|
238
322
|
ValueError("provided field does not have two horizontal dimension")
|
|
239
323
|
|
|
240
|
-
title = "%s, ntides = %i" % (field.long_name, self.ds[
|
|
324
|
+
title = "%s, ntides = %i" % (field.long_name, self.ds[var_name].ntides[ntides])
|
|
241
325
|
|
|
242
326
|
vmax = max(field.max(), -field.min())
|
|
243
327
|
vmin = -vmax
|
|
@@ -457,6 +541,9 @@ class TidalForcing(ROMSToolsMixins):
|
|
|
457
541
|
|
|
458
542
|
# Update var_names dictionary
|
|
459
543
|
var_names = {**data.var_names, "pot_Re": "pot_Re", "pot_Im": "pot_Im"}
|
|
544
|
+
var_names.pop("sal_Re", None) # Remove "sal_Re" if it exists
|
|
545
|
+
var_names.pop("sal_Im", None) # Remove "sal_Im" if it exists
|
|
546
|
+
|
|
460
547
|
object.__setattr__(data, "var_names", var_names)
|
|
461
548
|
|
|
462
549
|
|