roms-tools 1.6.2__py3-none-any.whl → 1.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ci/environment.yml +1 -1
- roms_tools/__init__.py +1 -0
- roms_tools/_version.py +1 -1
- roms_tools/setup/boundary_forcing.py +13 -112
- roms_tools/setup/datasets.py +778 -191
- roms_tools/setup/download.py +30 -0
- roms_tools/setup/initial_conditions.py +14 -76
- roms_tools/setup/plot.py +77 -15
- roms_tools/setup/river_forcing.py +589 -0
- roms_tools/setup/surface_forcing.py +10 -112
- roms_tools/setup/tides.py +6 -67
- roms_tools/setup/utils.py +259 -1
- roms_tools/tests/test_setup/test_boundary_forcing.py +0 -2
- 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 +157 -130
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/abs_time/.zattrs +1 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/bry_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/month/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/month/.zattrs +6 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/month/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_north/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_south/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/.zattrs +1 -1
- 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 +39 -12
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/abs_time/.zattrs +1 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/dust/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/dust_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/iron/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/iron_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/month/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/month/.zattrs +6 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/month/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nhy/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nhy_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nox/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nox_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air_alt/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/.zattrs +3 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/.zgroup +3 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/.zmetadata +214 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/abs_time/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/abs_time/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/abs_time/0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/month/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/month/.zattrs +6 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/month/0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_name/.zarray +24 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_name/.zattrs +6 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_name/0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_time/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_time/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_time/0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_tracer/.zarray +24 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_tracer/.zattrs +10 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_tracer/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_volume/.zarray +22 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_volume/.zattrs +9 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_volume/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/tracer_name/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/tracer_name/.zattrs +6 -0
- roms_tools/tests/test_setup/test_data/river_forcing.zarr/tracer_name/0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zattrs +1 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zgroup +3 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zmetadata +185 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/abs_time/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/abs_time/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/abs_time/0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_name/.zarray +24 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_name/.zattrs +6 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_name/0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_time/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_time/.zattrs +7 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_time/0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_tracer/.zarray +24 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_tracer/.zattrs +10 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_tracer/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_volume/.zarray +22 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_volume/.zattrs +9 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_volume/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_name/.zarray +20 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_name/.zattrs +6 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_name/0 +0 -0
- roms_tools/tests/test_setup/test_initial_conditions.py +0 -2
- roms_tools/tests/test_setup/test_river_forcing.py +366 -0
- roms_tools/tests/test_setup/test_surface_forcing.py +0 -2
- roms_tools/tests/test_setup/test_tides.py +0 -2
- roms_tools/tests/test_setup/test_validation.py +4 -0
- roms_tools/utils.py +12 -10
- {roms_tools-1.6.2.dist-info → roms_tools-1.7.0.dist-info}/METADATA +5 -5
- {roms_tools-1.6.2.dist-info → roms_tools-1.7.0.dist-info}/RECORD +221 -168
- {roms_tools-1.6.2.dist-info → roms_tools-1.7.0.dist-info}/WHEEL +1 -1
- {roms_tools-1.6.2.dist-info → roms_tools-1.7.0.dist-info}/LICENSE +0 -0
- {roms_tools-1.6.2.dist-info → roms_tools-1.7.0.dist-info}/top_level.txt +0 -0
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import xarray as xr
|
|
2
|
-
import pandas as pd
|
|
3
|
-
import yaml
|
|
4
2
|
import importlib.metadata
|
|
5
|
-
from dataclasses import dataclass, field
|
|
3
|
+
from dataclasses import dataclass, field
|
|
6
4
|
from roms_tools.setup.grid import Grid
|
|
7
5
|
from datetime import datetime
|
|
8
6
|
import numpy as np
|
|
@@ -22,6 +20,9 @@ from roms_tools.setup.utils import (
|
|
|
22
20
|
save_datasets,
|
|
23
21
|
get_target_coords,
|
|
24
22
|
rotate_velocities,
|
|
23
|
+
convert_to_roms_time,
|
|
24
|
+
_to_yaml,
|
|
25
|
+
_from_yaml,
|
|
25
26
|
)
|
|
26
27
|
from roms_tools.setup.plot import _plot
|
|
27
28
|
import matplotlib.pyplot as plt
|
|
@@ -302,38 +303,9 @@ class SurfaceForcing:
|
|
|
302
303
|
ds = self._add_global_metadata(ds)
|
|
303
304
|
|
|
304
305
|
# Convert the time coordinate to the format expected by ROMS
|
|
305
|
-
|
|
306
|
-
ds.
|
|
307
|
-
|
|
308
|
-
ds = ds.assign_coords(
|
|
309
|
-
{"abs_time": np.datetime64(self.model_reference_date) + ds["time"]}
|
|
310
|
-
)
|
|
311
|
-
# Convert to pandas TimedeltaIndex
|
|
312
|
-
timedelta_index = pd.to_timedelta(ds["time"].values)
|
|
313
|
-
|
|
314
|
-
# Determine the start of the year for the base_datetime
|
|
315
|
-
start_of_year = datetime(self.model_reference_date.year, 1, 1)
|
|
316
|
-
|
|
317
|
-
# Calculate the offset from midnight of the new year
|
|
318
|
-
offset = self.model_reference_date - start_of_year
|
|
319
|
-
|
|
320
|
-
# Convert the timedelta to nanoseconds first, then to days
|
|
321
|
-
sfc_time = xr.DataArray(
|
|
322
|
-
(timedelta_index - offset).view("int64") / 3600 / 24 * 1e-9,
|
|
323
|
-
dims="time",
|
|
324
|
-
)
|
|
325
|
-
else:
|
|
326
|
-
# Preserve absolute time coordinate for readability
|
|
327
|
-
ds = ds.assign_coords({"abs_time": ds["time"]})
|
|
328
|
-
|
|
329
|
-
sfc_time = (
|
|
330
|
-
(ds["time"] - np.datetime64(self.model_reference_date)).astype(
|
|
331
|
-
"float64"
|
|
332
|
-
)
|
|
333
|
-
/ 3600
|
|
334
|
-
/ 24
|
|
335
|
-
* 1e-9
|
|
336
|
-
)
|
|
306
|
+
ds, sfc_time = convert_to_roms_time(
|
|
307
|
+
ds, self.model_reference_date, data.climatology
|
|
308
|
+
)
|
|
337
309
|
|
|
338
310
|
if self.type == "physics":
|
|
339
311
|
time_coords = ["time"]
|
|
@@ -347,14 +319,6 @@ class SurfaceForcing:
|
|
|
347
319
|
]
|
|
348
320
|
for time_coord in time_coords:
|
|
349
321
|
ds = ds.assign_coords({time_coord: sfc_time})
|
|
350
|
-
ds[time_coord].attrs[
|
|
351
|
-
"long_name"
|
|
352
|
-
] = f"days since {str(self.model_reference_date)}"
|
|
353
|
-
ds[time_coord].encoding["units"] = "days"
|
|
354
|
-
ds[time_coord].attrs["units"] = "days"
|
|
355
|
-
if data.climatology:
|
|
356
|
-
ds[time_coord].attrs["cycle_length"] = 365.25
|
|
357
|
-
ds.encoding["unlimited_dims"] = "time"
|
|
358
322
|
|
|
359
323
|
if self.type == "bgc":
|
|
360
324
|
ds = ds.drop_vars(["time"])
|
|
@@ -579,49 +543,8 @@ class SurfaceForcing:
|
|
|
579
543
|
filepath : Union[str, Path]
|
|
580
544
|
The path to the YAML file where the parameters will be saved.
|
|
581
545
|
"""
|
|
582
|
-
filepath = Path(filepath)
|
|
583
546
|
|
|
584
|
-
|
|
585
|
-
grid_data = asdict(self.grid)
|
|
586
|
-
grid_data.pop("ds", None) # Exclude non-serializable fields
|
|
587
|
-
grid_data.pop("straddle", None)
|
|
588
|
-
|
|
589
|
-
# Include the version of roms-tools
|
|
590
|
-
try:
|
|
591
|
-
roms_tools_version = importlib.metadata.version("roms-tools")
|
|
592
|
-
except importlib.metadata.PackageNotFoundError:
|
|
593
|
-
roms_tools_version = "unknown"
|
|
594
|
-
|
|
595
|
-
# Create header
|
|
596
|
-
header = f"---\nroms_tools_version: {roms_tools_version}\n---\n"
|
|
597
|
-
|
|
598
|
-
# Create YAML data for Grid and optional attributes
|
|
599
|
-
grid_yaml_data = {"Grid": grid_data}
|
|
600
|
-
|
|
601
|
-
# Combine all sections
|
|
602
|
-
surface_forcing_data = {
|
|
603
|
-
"SurfaceForcing": {
|
|
604
|
-
"start_time": self.start_time.isoformat(),
|
|
605
|
-
"end_time": self.end_time.isoformat(),
|
|
606
|
-
"source": self.source,
|
|
607
|
-
"type": self.type,
|
|
608
|
-
"correct_radiation": self.correct_radiation,
|
|
609
|
-
"use_coarse_grid": self.use_coarse_grid,
|
|
610
|
-
"model_reference_date": self.model_reference_date.isoformat(),
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
# Merge YAML data while excluding empty sections
|
|
615
|
-
yaml_data = {
|
|
616
|
-
**grid_yaml_data,
|
|
617
|
-
**surface_forcing_data,
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
with filepath.open("w") as file:
|
|
621
|
-
# Write header
|
|
622
|
-
file.write(header)
|
|
623
|
-
# Write YAML data
|
|
624
|
-
yaml.dump(yaml_data, file, default_flow_style=False, sort_keys=False)
|
|
547
|
+
_to_yaml(self, filepath)
|
|
625
548
|
|
|
626
549
|
@classmethod
|
|
627
550
|
def from_yaml(
|
|
@@ -642,33 +565,8 @@ class SurfaceForcing:
|
|
|
642
565
|
An instance of the SurfaceForcing class.
|
|
643
566
|
"""
|
|
644
567
|
filepath = Path(filepath)
|
|
645
|
-
# Read the entire file content
|
|
646
|
-
with filepath.open("r") as file:
|
|
647
|
-
file_content = file.read()
|
|
648
|
-
|
|
649
|
-
# Split the content into YAML documents
|
|
650
|
-
documents = list(yaml.safe_load_all(file_content))
|
|
651
|
-
|
|
652
|
-
surface_forcing_data = None
|
|
653
|
-
|
|
654
|
-
# Process the YAML documents
|
|
655
|
-
for doc in documents:
|
|
656
|
-
if doc is None:
|
|
657
|
-
continue
|
|
658
|
-
if "SurfaceForcing" in doc:
|
|
659
|
-
surface_forcing_data = doc["SurfaceForcing"]
|
|
660
|
-
|
|
661
|
-
if surface_forcing_data is None:
|
|
662
|
-
raise ValueError("No SurfaceForcing configuration found in the YAML file.")
|
|
663
|
-
|
|
664
|
-
# Convert from string to datetime
|
|
665
|
-
for date_string in ["model_reference_date", "start_time", "end_time"]:
|
|
666
|
-
surface_forcing_data[date_string] = datetime.fromisoformat(
|
|
667
|
-
surface_forcing_data[date_string]
|
|
668
|
-
)
|
|
669
568
|
|
|
670
|
-
# Create Grid instance from the YAML file
|
|
671
569
|
grid = Grid.from_yaml(filepath)
|
|
570
|
+
params = _from_yaml(cls, filepath)
|
|
672
571
|
|
|
673
|
-
|
|
674
|
-
return cls(grid=grid, **surface_forcing_data, use_dask=use_dask)
|
|
572
|
+
return cls(grid=grid, **params, use_dask=use_dask)
|
roms_tools/setup/tides.py
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
import xarray as xr
|
|
3
3
|
import numpy as np
|
|
4
|
-
import yaml
|
|
5
|
-
import importlib.metadata
|
|
6
4
|
from typing import Dict, Union, List
|
|
7
|
-
|
|
8
|
-
from dataclasses import dataclass, field
|
|
5
|
+
import importlib.metadata
|
|
6
|
+
from dataclasses import dataclass, field
|
|
9
7
|
from roms_tools.setup.grid import Grid
|
|
10
8
|
from roms_tools.setup.plot import _plot
|
|
11
9
|
from roms_tools.setup.datasets import TPXODataset
|
|
@@ -19,6 +17,8 @@ from roms_tools.setup.utils import (
|
|
|
19
17
|
get_target_coords,
|
|
20
18
|
rotate_velocities,
|
|
21
19
|
get_vector_pairs,
|
|
20
|
+
_to_yaml,
|
|
21
|
+
_from_yaml,
|
|
22
22
|
)
|
|
23
23
|
from roms_tools.setup.regrid import LateralRegrid
|
|
24
24
|
import matplotlib.pyplot as plt
|
|
@@ -418,42 +418,8 @@ class TidalForcing:
|
|
|
418
418
|
filepath : Union[str, Path]
|
|
419
419
|
The path to the YAML file where the parameters will be saved.
|
|
420
420
|
"""
|
|
421
|
-
filepath = Path(filepath)
|
|
422
|
-
|
|
423
|
-
grid_data = asdict(self.grid)
|
|
424
|
-
grid_data.pop("ds", None) # Exclude non-serializable fields
|
|
425
|
-
grid_data.pop("straddle", None)
|
|
426
|
-
|
|
427
|
-
# Include the version of roms-tools
|
|
428
|
-
try:
|
|
429
|
-
roms_tools_version = importlib.metadata.version("roms-tools")
|
|
430
|
-
except importlib.metadata.PackageNotFoundError:
|
|
431
|
-
roms_tools_version = "unknown"
|
|
432
|
-
|
|
433
|
-
# Create header
|
|
434
|
-
header = f"---\nroms_tools_version: {roms_tools_version}\n---\n"
|
|
435
421
|
|
|
436
|
-
|
|
437
|
-
grid_yaml_data = {"Grid": grid_data}
|
|
438
|
-
|
|
439
|
-
# Extract tidal forcing data
|
|
440
|
-
tidal_forcing_data = {
|
|
441
|
-
"TidalForcing": {
|
|
442
|
-
"source": self.source,
|
|
443
|
-
"ntides": self.ntides,
|
|
444
|
-
"allan_factor": self.allan_factor,
|
|
445
|
-
"model_reference_date": self.model_reference_date.isoformat(),
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
# Combine both sections
|
|
450
|
-
yaml_data = {**grid_yaml_data, **tidal_forcing_data}
|
|
451
|
-
|
|
452
|
-
with filepath.open("w") as file:
|
|
453
|
-
# Write header
|
|
454
|
-
file.write(header)
|
|
455
|
-
# Write YAML data
|
|
456
|
-
yaml.dump(yaml_data, file, default_flow_style=False, sort_keys=False)
|
|
422
|
+
_to_yaml(self, filepath)
|
|
457
423
|
|
|
458
424
|
@classmethod
|
|
459
425
|
def from_yaml(
|
|
@@ -474,36 +440,9 @@ class TidalForcing:
|
|
|
474
440
|
An instance of the TidalForcing class.
|
|
475
441
|
"""
|
|
476
442
|
filepath = Path(filepath)
|
|
477
|
-
# Read the entire file content
|
|
478
|
-
with filepath.open("r") as file:
|
|
479
|
-
file_content = file.read()
|
|
480
|
-
|
|
481
|
-
# Split the content into YAML documents
|
|
482
|
-
documents = list(yaml.safe_load_all(file_content))
|
|
483
|
-
|
|
484
|
-
tidal_forcing_data = None
|
|
485
|
-
|
|
486
|
-
# Process the YAML documents
|
|
487
|
-
for doc in documents:
|
|
488
|
-
if doc is None:
|
|
489
|
-
continue
|
|
490
|
-
if "TidalForcing" in doc:
|
|
491
|
-
tidal_forcing_data = doc["TidalForcing"]
|
|
492
|
-
break
|
|
493
|
-
|
|
494
|
-
if tidal_forcing_data is None:
|
|
495
|
-
raise ValueError("No TidalForcing configuration found in the YAML file.")
|
|
496
|
-
|
|
497
|
-
# Convert the model_reference_date from string to datetime
|
|
498
|
-
tidal_forcing_params = tidal_forcing_data
|
|
499
|
-
tidal_forcing_params["model_reference_date"] = datetime.fromisoformat(
|
|
500
|
-
tidal_forcing_params["model_reference_date"]
|
|
501
|
-
)
|
|
502
443
|
|
|
503
|
-
# Create Grid instance from the YAML file
|
|
504
444
|
grid = Grid.from_yaml(filepath)
|
|
505
|
-
|
|
506
|
-
# Create and return an instance of TidalForcing
|
|
445
|
+
tidal_forcing_params = _from_yaml(cls, filepath)
|
|
507
446
|
return cls(grid=grid, **tidal_forcing_params, use_dask=use_dask)
|
|
508
447
|
|
|
509
448
|
def _correct_tides(self, data):
|
roms_tools/setup/utils.py
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import xarray as xr
|
|
2
2
|
import numpy as np
|
|
3
|
-
from typing import Union
|
|
3
|
+
from typing import Union, Any, Dict, Type
|
|
4
4
|
import pandas as pd
|
|
5
5
|
import cftime
|
|
6
6
|
from roms_tools.utils import partition
|
|
7
7
|
from pathlib import Path
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from dataclasses import fields, asdict
|
|
10
|
+
import importlib.metadata
|
|
11
|
+
import yaml
|
|
8
12
|
|
|
9
13
|
|
|
10
14
|
def nan_check(field, mask, error_message=None) -> None:
|
|
@@ -921,3 +925,257 @@ def get_vector_pairs(variable_info):
|
|
|
921
925
|
processed.update([var_name, vector_pair])
|
|
922
926
|
|
|
923
927
|
return vector_pairs
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
def gc_dist(lon1, lat1, lon2, lat2):
|
|
931
|
+
"""Calculate the great circle distance between two points on the Earth's surface.
|
|
932
|
+
Latitude and longitude must be provided in degrees (they will be converted to
|
|
933
|
+
radians).
|
|
934
|
+
|
|
935
|
+
The function uses the Haversine formula to compute the shortest distance
|
|
936
|
+
along the surface of a sphere (Earth), assuming the Earth is a perfect sphere.
|
|
937
|
+
|
|
938
|
+
Parameters
|
|
939
|
+
----------
|
|
940
|
+
lon1, lat1 : float
|
|
941
|
+
Longitude and latitude of the first point in degrees.
|
|
942
|
+
lon2, lat2 : float
|
|
943
|
+
Longitude and latitude of the second point in degrees.
|
|
944
|
+
|
|
945
|
+
Returns
|
|
946
|
+
-------
|
|
947
|
+
dis : float
|
|
948
|
+
The great circle distance between the two points in meters.
|
|
949
|
+
This is the shortest distance along the surface of a sphere (Earth).
|
|
950
|
+
|
|
951
|
+
Notes
|
|
952
|
+
-----
|
|
953
|
+
The radius of the Earth is taken to be 6371315 meters.
|
|
954
|
+
"""
|
|
955
|
+
# Convert degrees to radians
|
|
956
|
+
d2r = np.pi / 180
|
|
957
|
+
lon1 = lon1 * d2r
|
|
958
|
+
lat1 = lat1 * d2r
|
|
959
|
+
lon2 = lon2 * d2r
|
|
960
|
+
lat2 = lat2 * d2r
|
|
961
|
+
|
|
962
|
+
# Difference in latitudes and longitudes
|
|
963
|
+
dlat = lat2 - lat1
|
|
964
|
+
dlon = lon2 - lon1
|
|
965
|
+
|
|
966
|
+
# Haversine formula
|
|
967
|
+
dang = 2 * np.arcsin(
|
|
968
|
+
np.sqrt(
|
|
969
|
+
np.sin(dlat / 2) ** 2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon / 2) ** 2
|
|
970
|
+
)
|
|
971
|
+
)
|
|
972
|
+
|
|
973
|
+
# Radius of the Earth in meters
|
|
974
|
+
r_earth = 6371315.0
|
|
975
|
+
|
|
976
|
+
# Distance in meters
|
|
977
|
+
dis = r_earth * dang
|
|
978
|
+
|
|
979
|
+
return dis
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
def convert_to_roms_time(ds, model_reference_date, climatology, time_name="time"):
|
|
983
|
+
|
|
984
|
+
if climatology:
|
|
985
|
+
ds.attrs["climatology"] = str(True)
|
|
986
|
+
month = xr.DataArray(range(1, 13), dims=time_name)
|
|
987
|
+
month.attrs["long_name"] = "Month index (1-12)"
|
|
988
|
+
ds = ds.assign_coords({"month": month})
|
|
989
|
+
# Preserve absolute time coordinate for readability
|
|
990
|
+
abs_time = np.datetime64(model_reference_date) + ds[time_name]
|
|
991
|
+
# Convert to pandas TimedeltaIndex
|
|
992
|
+
timedelta_index = pd.to_timedelta(ds[time_name].values)
|
|
993
|
+
|
|
994
|
+
# Determine the start of the year for the base_datetime
|
|
995
|
+
start_of_year = datetime(model_reference_date.year, 1, 1)
|
|
996
|
+
|
|
997
|
+
# Calculate the offset from midnight of the new year
|
|
998
|
+
offset = model_reference_date - start_of_year
|
|
999
|
+
|
|
1000
|
+
# Convert the timedelta to nanoseconds first, then to days
|
|
1001
|
+
time = xr.DataArray(
|
|
1002
|
+
(timedelta_index - offset).view("int64") / 3600 / 24 * 1e-9,
|
|
1003
|
+
dims=time_name,
|
|
1004
|
+
)
|
|
1005
|
+
time.attrs["cycle_length"] = 365.25
|
|
1006
|
+
|
|
1007
|
+
else:
|
|
1008
|
+
# Preserve absolute time coordinate for readability
|
|
1009
|
+
abs_time = ds[time_name]
|
|
1010
|
+
|
|
1011
|
+
time = (
|
|
1012
|
+
(ds[time_name] - np.datetime64(model_reference_date)).astype("float64")
|
|
1013
|
+
/ 3600
|
|
1014
|
+
/ 24
|
|
1015
|
+
* 1e-9
|
|
1016
|
+
)
|
|
1017
|
+
|
|
1018
|
+
attrs = [key for key in abs_time.attrs]
|
|
1019
|
+
for attr in attrs:
|
|
1020
|
+
del abs_time.attrs[attr]
|
|
1021
|
+
abs_time.attrs["long_name"] = "absolute time"
|
|
1022
|
+
ds = ds.assign_coords({"abs_time": abs_time})
|
|
1023
|
+
|
|
1024
|
+
time.attrs["long_name"] = f"relative time: days since {str(model_reference_date)}"
|
|
1025
|
+
time.encoding["units"] = "days"
|
|
1026
|
+
time.attrs["units"] = "days"
|
|
1027
|
+
ds.encoding["unlimited_dims"] = "time"
|
|
1028
|
+
|
|
1029
|
+
return ds, time
|
|
1030
|
+
|
|
1031
|
+
|
|
1032
|
+
def _to_yaml(forcing_object, filepath: Union[str, Path]) -> None:
|
|
1033
|
+
"""Serialize a forcing object (including its grid) into a YAML file.
|
|
1034
|
+
|
|
1035
|
+
This function serializes a dataclass object (forcing_object) and its associated
|
|
1036
|
+
`grid` attribute into a YAML file. It includes additional metadata, such as
|
|
1037
|
+
the version of the `roms-tools` package, and omits fields like `grid` and `ds`
|
|
1038
|
+
that are not serializable or meant to be excluded.
|
|
1039
|
+
|
|
1040
|
+
The function also converts datetime fields to ISO format strings for proper
|
|
1041
|
+
serialization.
|
|
1042
|
+
|
|
1043
|
+
Parameters
|
|
1044
|
+
----------
|
|
1045
|
+
forcing_object : object
|
|
1046
|
+
The object that contains the forcing data, typically a dataclass with attributes
|
|
1047
|
+
such as `grid`, `start_time`, `end_time`, etc.
|
|
1048
|
+
filepath : Union[str, Path]
|
|
1049
|
+
The path where the serialized YAML file will be saved.
|
|
1050
|
+
|
|
1051
|
+
Returns
|
|
1052
|
+
-------
|
|
1053
|
+
None
|
|
1054
|
+
The function writes the serialized data directly to a YAML file at the specified path.
|
|
1055
|
+
"""
|
|
1056
|
+
|
|
1057
|
+
# Convert the filepath to a Path object
|
|
1058
|
+
filepath = Path(filepath)
|
|
1059
|
+
|
|
1060
|
+
# Step 1: Serialize Grid data
|
|
1061
|
+
# Convert the grid attribute to a dictionary and remove non-serializable fields
|
|
1062
|
+
grid_data = asdict(forcing_object.grid)
|
|
1063
|
+
grid_data.pop("ds", None) # Remove 'ds' attribute (non-serializable)
|
|
1064
|
+
grid_data.pop("straddle", None) # Remove 'straddle' if it's non-essential
|
|
1065
|
+
grid_yaml_data = {"Grid": grid_data}
|
|
1066
|
+
|
|
1067
|
+
# Step 2: Get ROMS Tools version
|
|
1068
|
+
# Fetch the version of the 'roms-tools' package for inclusion in the YAML header
|
|
1069
|
+
try:
|
|
1070
|
+
roms_tools_version = importlib.metadata.version("roms-tools")
|
|
1071
|
+
except importlib.metadata.PackageNotFoundError:
|
|
1072
|
+
roms_tools_version = "unknown"
|
|
1073
|
+
|
|
1074
|
+
# Create YAML header with version information
|
|
1075
|
+
header = f"---\nroms_tools_version: {roms_tools_version}\n---\n"
|
|
1076
|
+
|
|
1077
|
+
# Step 3: Prepare Forcing Data
|
|
1078
|
+
# Prepare the forcing object fields, excluding 'grid' and 'ds'
|
|
1079
|
+
forcing_data = {}
|
|
1080
|
+
field_names = [field.name for field in fields(forcing_object)]
|
|
1081
|
+
filtered_field_names = [
|
|
1082
|
+
param
|
|
1083
|
+
for param in field_names
|
|
1084
|
+
if param not in ("grid", "ds", "use_dask", "climatology")
|
|
1085
|
+
]
|
|
1086
|
+
|
|
1087
|
+
for field_name in filtered_field_names:
|
|
1088
|
+
# Retrieve the value of each field using getattr
|
|
1089
|
+
value = getattr(forcing_object, field_name)
|
|
1090
|
+
|
|
1091
|
+
# If the field is a datetime object, convert it to ISO format
|
|
1092
|
+
if isinstance(value, datetime):
|
|
1093
|
+
value = value.isoformat()
|
|
1094
|
+
|
|
1095
|
+
# Add the field and its value to the forcing_data dictionary
|
|
1096
|
+
forcing_data[field_name] = value
|
|
1097
|
+
|
|
1098
|
+
# Step 4: Combine Grid and Forcing Data
|
|
1099
|
+
# Combine grid and forcing data into a single dictionary for the final YAML content
|
|
1100
|
+
yaml_data = {
|
|
1101
|
+
**grid_yaml_data, # Add the grid data to the final YAML structure
|
|
1102
|
+
forcing_object.__class__.__name__: forcing_data, # Include the serialized forcing object data
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
# Step 5: Write to YAML file
|
|
1106
|
+
with filepath.open("w") as file:
|
|
1107
|
+
# Write the header first
|
|
1108
|
+
file.write(header)
|
|
1109
|
+
# Write the serialized YAML data
|
|
1110
|
+
yaml.dump(yaml_data, file, default_flow_style=False, sort_keys=False)
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
def _from_yaml(forcing_object: Type, filepath: Union[str, Path]) -> Dict[str, Any]:
|
|
1114
|
+
"""Extract the configuration data for a given forcing object from a YAML file.
|
|
1115
|
+
|
|
1116
|
+
This function reads a YAML file, searches for the configuration data associated
|
|
1117
|
+
with the class name of the forcing object, and returns the configuration data
|
|
1118
|
+
as a dictionary. The dictionary contains the forcing parameters extracted from
|
|
1119
|
+
the YAML file, with any date fields converted from ISO format.
|
|
1120
|
+
|
|
1121
|
+
Parameters
|
|
1122
|
+
----------
|
|
1123
|
+
filepath : Union[str, Path]
|
|
1124
|
+
The path to the YAML file from which the parameters will be read.
|
|
1125
|
+
forcing_object : Type
|
|
1126
|
+
The class type (e.g., TidalForcing) whose configuration data is to be loaded
|
|
1127
|
+
from the YAML file. The class name is used to locate the relevant data in
|
|
1128
|
+
the YAML structure.
|
|
1129
|
+
|
|
1130
|
+
Returns
|
|
1131
|
+
-------
|
|
1132
|
+
dict
|
|
1133
|
+
A dictionary containing the forcing parameters extracted from the YAML file.
|
|
1134
|
+
This dictionary contains key-value pairs where the keys are the parameter
|
|
1135
|
+
names, and the values are the corresponding values from the YAML file.
|
|
1136
|
+
Any date fields are converted from ISO format if necessary.
|
|
1137
|
+
|
|
1138
|
+
Raises
|
|
1139
|
+
------
|
|
1140
|
+
ValueError
|
|
1141
|
+
If no configuration for the specified class name is found in the YAML file.
|
|
1142
|
+
"""
|
|
1143
|
+
|
|
1144
|
+
# Read the entire file content
|
|
1145
|
+
with filepath.open("r") as file:
|
|
1146
|
+
file_content = file.read()
|
|
1147
|
+
|
|
1148
|
+
# Split the content into YAML documents
|
|
1149
|
+
documents = list(yaml.safe_load_all(file_content))
|
|
1150
|
+
|
|
1151
|
+
forcing_data = None
|
|
1152
|
+
forcing_object_name = forcing_object.__name__
|
|
1153
|
+
|
|
1154
|
+
# Process the YAML documents to find the forcing data for the given object
|
|
1155
|
+
for doc in documents:
|
|
1156
|
+
if doc is None:
|
|
1157
|
+
continue
|
|
1158
|
+
if forcing_object_name in doc:
|
|
1159
|
+
forcing_data = doc[forcing_object_name]
|
|
1160
|
+
break
|
|
1161
|
+
|
|
1162
|
+
if forcing_data is None:
|
|
1163
|
+
raise ValueError(
|
|
1164
|
+
f"No {forcing_object_name} configuration found in the YAML file."
|
|
1165
|
+
)
|
|
1166
|
+
|
|
1167
|
+
# Convert any date fields from ISO format if necessary
|
|
1168
|
+
for key, value in forcing_data.items():
|
|
1169
|
+
forcing_data[key] = _convert_from_iso_format(value)
|
|
1170
|
+
|
|
1171
|
+
# Return the forcing data as a dictionary
|
|
1172
|
+
return forcing_data
|
|
1173
|
+
|
|
1174
|
+
|
|
1175
|
+
def _convert_from_iso_format(value):
|
|
1176
|
+
try:
|
|
1177
|
+
# Return the parsed datetime object if successful
|
|
1178
|
+
return datetime.fromisoformat(str(value))
|
|
1179
|
+
except ValueError:
|
|
1180
|
+
# Return None or raise an exception if parsing fails
|
|
1181
|
+
return value
|
|
@@ -391,9 +391,7 @@ def test_from_yaml_missing_boundary_forcing(tmp_path, request, use_dask):
|
|
|
391
391
|
center_lat: 61
|
|
392
392
|
rot: -20
|
|
393
393
|
topography_source: ETOPO5
|
|
394
|
-
smooth_factor: 8
|
|
395
394
|
hmin: 5.0
|
|
396
|
-
rmax: 0.2
|
|
397
395
|
"""
|
|
398
396
|
)
|
|
399
397
|
# Create a temporary filepath using the tmp_path fixture
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"end_time": "2021-06-30 00:00:00",
|
|
4
4
|
"hc": 250.0,
|
|
5
5
|
"model_reference_date": "2000-01-01 00:00:00",
|
|
6
|
-
"roms_tools_version": "0.1.
|
|
6
|
+
"roms_tools_version": "0.1.dev169+dirty",
|
|
7
7
|
"source": "CESM_REGRIDDED",
|
|
8
8
|
"start_time": "2021-06-29 00:00:00",
|
|
9
9
|
"theta_b": 2.0,
|