roms-tools 3.3.0__py3-none-any.whl → 3.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- roms_tools/__init__.py +1 -1
- roms_tools/analysis/cdr_ensemble.py +10 -13
- roms_tools/analysis/roms_output.py +5 -304
- roms_tools/{download.py → datasets/download.py} +1 -0
- roms_tools/{setup → datasets}/lat_lon_datasets.py +88 -64
- roms_tools/{setup → datasets}/river_datasets.py +9 -4
- roms_tools/datasets/roms_dataset.py +854 -0
- roms_tools/datasets/utils.py +487 -0
- roms_tools/{setup/fill.py → fill.py} +110 -13
- roms_tools/plot.py +4 -4
- roms_tools/regrid.py +76 -0
- roms_tools/setup/boundary_forcing.py +53 -45
- roms_tools/setup/cdr_release.py +2 -4
- roms_tools/setup/grid.py +46 -15
- roms_tools/setup/initial_conditions.py +330 -71
- roms_tools/setup/mask.py +2 -5
- roms_tools/setup/nesting.py +13 -6
- roms_tools/setup/river_forcing.py +4 -4
- roms_tools/setup/surface_forcing.py +15 -11
- roms_tools/setup/tides.py +7 -6
- roms_tools/setup/topography.py +10 -2
- roms_tools/setup/utils.py +292 -666
- roms_tools/tests/test_analysis/test_cdr_ensemble.py +4 -6
- roms_tools/tests/test_analysis/test_roms_output.py +1 -220
- roms_tools/tests/{test_setup → test_datasets}/test_lat_lon_datasets.py +4 -4
- roms_tools/tests/{test_setup → test_datasets}/test_river_datasets.py +1 -1
- roms_tools/tests/test_datasets/test_roms_dataset.py +743 -0
- roms_tools/tests/test_datasets/test_utils.py +527 -0
- roms_tools/tests/{test_setup/test_fill.py → test_fill.py} +72 -9
- roms_tools/tests/test_regrid.py +120 -1
- roms_tools/tests/test_setup/test_boundary_forcing.py +57 -138
- roms_tools/tests/test_setup/test_cdr_release.py +4 -5
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zarr.json +293 -2021
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zarr.json +294 -2022
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/ALK/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/ALK_west → initial_conditions_from_roms.zarr/ALK}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/ALK_ALT_CO2/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west → initial_conditions_from_roms.zarr/ALK_ALT_CO2}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/Cs_r/c/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_west → initial_conditions_from_roms.zarr/Cs_r}/zarr.json +5 -12
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/Cs_w/c/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/diatFe_west → initial_conditions_from_roms.zarr/Cs_w}/zarr.json +3 -10
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DIC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/DOCr_west → initial_conditions_from_roms.zarr/DIC}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DIC_ALT_CO2/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DIC_ALT_CO2/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DOC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DOC/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DOCr/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west → initial_conditions_from_roms.zarr/DOCr}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DON/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DON/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DONr/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DONr/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DOP/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DOP/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DOPr/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/DOPr/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/Fe/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/Fe/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/Lig/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/DOP_west → initial_conditions_from_roms.zarr/Lig}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/NH4/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/DON_west → initial_conditions_from_roms.zarr/NH4}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/NO3/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/NO3/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/O2/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/Lig_west → initial_conditions_from_roms.zarr/O2}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/PO4/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/PO4/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/SiO3/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/SiO3/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/abs_time/zarr.json +47 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/diatC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/diatC_west → initial_conditions_from_roms.zarr/diatC}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/diatChl/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/diatChl_west → initial_conditions_from_roms.zarr/diatChl}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/diatFe/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/O2_west → initial_conditions_from_roms.zarr/diatFe}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/diatP/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/DIC_west → initial_conditions_from_roms.zarr/diatP}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/diatSi/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/DOC_west → initial_conditions_from_roms.zarr/diatSi}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/diazC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/diazC/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/diazChl/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/diazChl_west → initial_conditions_from_roms.zarr/diazChl}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/diazFe/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/Fe_west → initial_conditions_from_roms.zarr/diazFe}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/diazP/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/diazP/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/ocean_time/c/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/ocean_time/zarr.json +47 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/salt/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_unified_climatology.zarr/ALK_west → initial_conditions_from_roms.zarr/salt}/zarr.json +12 -9
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/spC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/spC/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/spCaCO3/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/spCaCO3/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/spChl/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/spChl_west → initial_conditions_from_roms.zarr/spChl}/zarr.json +11 -8
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/spFe/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/spFe/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/spP/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/spP/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/temp/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/temp/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/u/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/{bgc_boundary_forcing_from_climatology.zarr/NH4_west → initial_conditions_from_roms.zarr/u}/zarr.json +12 -9
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/ubar/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/ubar/zarr.json +54 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/v/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/v/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/vbar/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/vbar/zarr.json +54 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/w/zarr.json +57 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/zarr.json +2481 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/zeta/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/zeta/zarr.json +54 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/zooC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_from_roms.zarr/zooC/zarr.json +57 -0
- roms_tools/tests/test_setup/test_grid.py +66 -1
- roms_tools/tests/test_setup/test_initial_conditions.py +130 -104
- roms_tools/tests/test_setup/test_nesting.py +2 -1
- roms_tools/tests/test_setup/test_surface_forcing.py +1 -1
- roms_tools/tests/test_setup/test_tides.py +1 -1
- roms_tools/tests/test_setup/test_utils.py +100 -15
- roms_tools/tests/test_setup/test_validation.py +15 -0
- roms_tools/tests/test_tiling/test_partition.py +63 -15
- roms_tools/tests/test_utils.py +365 -0
- roms_tools/tiling/partition.py +81 -211
- roms_tools/utils.py +360 -62
- {roms_tools-3.3.0.dist-info → roms_tools-3.5.0.dist-info}/METADATA +2 -3
- {roms_tools-3.3.0.dist-info → roms_tools-3.5.0.dist-info}/RECORD +137 -174
- {roms_tools-3.3.0.dist-info → roms_tools-3.5.0.dist-info}/WHEEL +1 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_west/zarr.json +0 -54
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_west/zarr.json +0 -54
- {roms_tools-3.3.0.dist-info → roms_tools-3.5.0.dist-info}/licenses/LICENSE +0 -0
- {roms_tools-3.3.0.dist-info → roms_tools-3.5.0.dist-info}/top_level.txt +0 -0
roms_tools/utils.py
CHANGED
|
@@ -10,6 +10,7 @@ from pathlib import Path
|
|
|
10
10
|
from typing import TypeAlias
|
|
11
11
|
|
|
12
12
|
import numpy as np
|
|
13
|
+
import pandas as pd
|
|
13
14
|
import xarray as xr
|
|
14
15
|
|
|
15
16
|
from roms_tools.constants import R_EARTH
|
|
@@ -476,96 +477,199 @@ def load_data(
|
|
|
476
477
|
return ds
|
|
477
478
|
|
|
478
479
|
|
|
479
|
-
def
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
480
|
+
def _interpolate_generic(
|
|
481
|
+
field: xr.DataArray,
|
|
482
|
+
dim_in: str,
|
|
483
|
+
dim_out: str,
|
|
484
|
+
method: str = "additive",
|
|
485
|
+
drop_coords: Sequence[str] | None = None,
|
|
486
|
+
pad_end: bool = False,
|
|
487
|
+
) -> xr.DataArray:
|
|
488
|
+
"""
|
|
489
|
+
Generic interpolation along one horizontal dimension.
|
|
487
490
|
|
|
488
491
|
Parameters
|
|
489
492
|
----------
|
|
490
493
|
field : xr.DataArray
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
494
|
+
Input array to interpolate.
|
|
495
|
+
dim_in : str
|
|
496
|
+
Dimension along which to interpolate (e.g., "xi_rho").
|
|
497
|
+
dim_out : str
|
|
498
|
+
New dimension name after interpolation (e.g., "xi_u").
|
|
499
|
+
method : str, default "additive"
|
|
500
|
+
Interpolation method:
|
|
501
|
+
- "additive": average adjacent points
|
|
502
|
+
- "multiplicative": multiply adjacent points (useful for masks)
|
|
503
|
+
drop_coords : Sequence[str] or None, optional
|
|
504
|
+
Coordinate variables to drop (e.g., ["lat_rho", "lon_rho"]).
|
|
505
|
+
pad_end : bool, default False
|
|
506
|
+
Whether to pad the last point with NaN (useful when interpolating back to rho grid).
|
|
499
507
|
|
|
500
508
|
Returns
|
|
501
509
|
-------
|
|
502
|
-
|
|
503
|
-
|
|
510
|
+
xr.DataArray
|
|
511
|
+
Interpolated array with dimension `dim_out`.
|
|
504
512
|
"""
|
|
505
|
-
if
|
|
506
|
-
|
|
507
|
-
|
|
513
|
+
if not isinstance(field, xr.DataArray):
|
|
514
|
+
raise TypeError(
|
|
515
|
+
"_interpolate_generic expects an xarray.DataArray, "
|
|
516
|
+
f"got {type(field).__name__}"
|
|
508
517
|
)
|
|
518
|
+
|
|
519
|
+
if drop_coords:
|
|
520
|
+
for coord in drop_coords:
|
|
521
|
+
if coord in field.coords:
|
|
522
|
+
field = field.drop_vars(coord)
|
|
523
|
+
|
|
524
|
+
if method == "additive":
|
|
525
|
+
interp = 0.5 * (field + field.shift(**{dim_in: 1}))
|
|
509
526
|
elif method == "multiplicative":
|
|
510
|
-
|
|
527
|
+
interp = field * field.shift(**{dim_in: 1})
|
|
511
528
|
else:
|
|
512
529
|
raise NotImplementedError(f"Unsupported method '{method}' specified.")
|
|
513
530
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
531
|
+
if pad_end:
|
|
532
|
+
pad_shape = {d: field.sizes[d] for d in field.dims}
|
|
533
|
+
pad_shape[dim_in] = 1
|
|
534
|
+
pad = xr.DataArray(
|
|
535
|
+
np.nan * np.ones(tuple(pad_shape[d] for d in field.dims)),
|
|
536
|
+
dims=field.dims,
|
|
537
|
+
)
|
|
538
|
+
interp = xr.concat([interp, pad], dim=dim_in)
|
|
539
|
+
else:
|
|
540
|
+
interp = interp.isel({dim_in: slice(1, None)})
|
|
541
|
+
|
|
542
|
+
interp = interp.swap_dims({dim_in: dim_out})
|
|
518
543
|
|
|
519
|
-
|
|
544
|
+
return interp
|
|
520
545
|
|
|
521
|
-
|
|
546
|
+
|
|
547
|
+
def interpolate_from_rho_to_u(
|
|
548
|
+
field: xr.DataArray, method: str = "additive"
|
|
549
|
+
) -> xr.DataArray:
|
|
550
|
+
"""Interpolate a field from rho points to u points (xi direction)."""
|
|
551
|
+
return _interpolate_generic(
|
|
552
|
+
field,
|
|
553
|
+
dim_in="xi_rho",
|
|
554
|
+
dim_out="xi_u",
|
|
555
|
+
method=method,
|
|
556
|
+
drop_coords=["lat_rho", "lon_rho", "eta_rho", "xi_rho"],
|
|
557
|
+
)
|
|
522
558
|
|
|
523
559
|
|
|
524
|
-
def interpolate_from_rho_to_v(
|
|
525
|
-
|
|
560
|
+
def interpolate_from_rho_to_v(
|
|
561
|
+
field: xr.DataArray, method: str = "additive"
|
|
562
|
+
) -> xr.DataArray:
|
|
563
|
+
"""Interpolate a field from rho points to v points (eta direction)."""
|
|
564
|
+
return _interpolate_generic(
|
|
565
|
+
field,
|
|
566
|
+
dim_in="eta_rho",
|
|
567
|
+
dim_out="eta_v",
|
|
568
|
+
method=method,
|
|
569
|
+
drop_coords=["lat_rho", "lon_rho", "eta_rho", "xi_rho"],
|
|
570
|
+
)
|
|
526
571
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
572
|
+
|
|
573
|
+
def interpolate_from_u_to_rho(
|
|
574
|
+
field: xr.DataArray, method: str = "additive"
|
|
575
|
+
) -> xr.DataArray:
|
|
576
|
+
"""Interpolate a field from u points back to rho points (xi direction)."""
|
|
577
|
+
return _interpolate_generic(
|
|
578
|
+
field,
|
|
579
|
+
dim_in="xi_u",
|
|
580
|
+
dim_out="xi_rho",
|
|
581
|
+
method=method,
|
|
582
|
+
drop_coords=["lat_u", "lon_u", "eta_rho", "xi_u"],
|
|
583
|
+
pad_end=True,
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
def interpolate_from_v_to_rho(
|
|
588
|
+
field: xr.DataArray, method: str = "additive"
|
|
589
|
+
) -> xr.DataArray:
|
|
590
|
+
"""Interpolate a field from v points back to rho points (eta direction)."""
|
|
591
|
+
return _interpolate_generic(
|
|
592
|
+
field,
|
|
593
|
+
dim_in="eta_v",
|
|
594
|
+
dim_out="eta_rho",
|
|
595
|
+
method=method,
|
|
596
|
+
drop_coords=["lat_v", "lon_v", "eta_v", "xi_rho"],
|
|
597
|
+
pad_end=True,
|
|
598
|
+
)
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
def rotate_velocities(
|
|
602
|
+
u: xr.DataArray,
|
|
603
|
+
v: xr.DataArray,
|
|
604
|
+
angle: xr.DataArray,
|
|
605
|
+
interpolate_before: bool = False,
|
|
606
|
+
interpolate_after: bool = False,
|
|
607
|
+
) -> tuple[xr.DataArray, xr.DataArray]:
|
|
608
|
+
"""
|
|
609
|
+
Rotate horizontal velocity components to align with a rotated grid.
|
|
610
|
+
|
|
611
|
+
This function rotates zonal (u) and meridional (v) velocity components
|
|
612
|
+
using a grid angle field. It can be used to:
|
|
613
|
+
|
|
614
|
+
1. Rotate model velocities from the ROMS model grid to a lat-lon reference frame.
|
|
615
|
+
2. Rotate lat-lon velocities onto the ROMS model grid.
|
|
616
|
+
|
|
617
|
+
Optionally, velocities can be interpolated between staggered C-grid
|
|
618
|
+
locations (u-, v-, and rho-points) before and/or after rotation.
|
|
532
619
|
|
|
533
620
|
Parameters
|
|
534
621
|
----------
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
622
|
+
u : xarray.DataArray
|
|
623
|
+
Zonal (east-west) velocity component defined on u-points.
|
|
624
|
+
v : xarray.DataArray
|
|
625
|
+
Meridional (north-south) velocity component defined on v-points.
|
|
626
|
+
angle : xarray.DataArray
|
|
627
|
+
Grid orientation angle in radians, defined at rho-points. This is the
|
|
628
|
+
ROMS grid angle: the angle between the model xi-direction and true east.
|
|
629
|
+
Positive values indicate that the model grid is rotated counterclockwise
|
|
630
|
+
relative to east (which is mathematically equivalent to rotating velocity
|
|
631
|
+
vectors clockwise).
|
|
632
|
+
The rotation transforms velocity components between earth-relative
|
|
633
|
+
(east/north) and grid-relative (xi/eta) coordinates. To reverse the
|
|
634
|
+
transformation (e.g., model → lat-lon), provide ``-angle``.
|
|
635
|
+
interpolate_before : bool, optional
|
|
636
|
+
If True, interpolate ``u`` and ``v`` to rho-points before rotation.
|
|
637
|
+
Default is False.
|
|
638
|
+
interpolate_after : bool, optional
|
|
639
|
+
If True, interpolate the rotated velocities back to u- and v-points
|
|
640
|
+
after rotation. Default is True.
|
|
544
641
|
|
|
545
642
|
Returns
|
|
546
643
|
-------
|
|
547
|
-
|
|
548
|
-
|
|
644
|
+
u_rot, v_rot : tuple of xarray.DataArray
|
|
645
|
+
Rotated velocity components. If ``interpolate_after`` is True, ``u_rot``
|
|
646
|
+
is defined on u-points and ``v_rot`` on v-points; otherwise, both are
|
|
647
|
+
defined at rho-points.
|
|
648
|
+
|
|
649
|
+
Notes
|
|
650
|
+
-----
|
|
651
|
+
The rotation follows the standard ROMS convention:
|
|
652
|
+
- ``u_rot = u * cos(angle) + v * sin(angle)``
|
|
653
|
+
- ``v_rot = v * cos(angle) - u * sin(angle)``
|
|
654
|
+
This function is versatile and can be used for both directions of rotation:
|
|
655
|
+
- Lat-lon → model grid: provide the grid angle.
|
|
656
|
+
- Model grid → lat-lon: provide the negative of the grid angle.
|
|
549
657
|
"""
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
)
|
|
554
|
-
elif method == "multiplicative":
|
|
555
|
-
field_interpolated = (field * field.shift(eta_rho=1)).isel(
|
|
556
|
-
eta_rho=slice(1, None)
|
|
557
|
-
)
|
|
558
|
-
else:
|
|
559
|
-
raise NotImplementedError(f"Unsupported method '{method}' specified.")
|
|
658
|
+
# Interpolate to rho-points
|
|
659
|
+
if interpolate_before:
|
|
660
|
+
u = interpolate_from_u_to_rho(u)
|
|
661
|
+
v = interpolate_from_v_to_rho(v)
|
|
560
662
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
field_interpolated = field_interpolated.drop_vars(var)
|
|
663
|
+
# Rotate velocities to grid orientation
|
|
664
|
+
u_rot = u * np.cos(angle) + v * np.sin(angle)
|
|
665
|
+
v_rot = v * np.cos(angle) - u * np.sin(angle)
|
|
565
666
|
|
|
566
|
-
|
|
667
|
+
# Interpolate to u- and v-points
|
|
668
|
+
if interpolate_after:
|
|
669
|
+
u_rot = interpolate_from_rho_to_u(u_rot)
|
|
670
|
+
v_rot = interpolate_from_rho_to_v(v_rot)
|
|
567
671
|
|
|
568
|
-
return
|
|
672
|
+
return u_rot, v_rot
|
|
569
673
|
|
|
570
674
|
|
|
571
675
|
def transpose_dimensions(da: xr.DataArray) -> xr.DataArray:
|
|
@@ -1031,3 +1135,197 @@ def get_pkg_error_msg(purpose: str, package_name: str, option_name: str) -> str:
|
|
|
1031
1135
|
• `pip install {package_name}` or
|
|
1032
1136
|
• `conda install {package_name}`
|
|
1033
1137
|
Alternatively, install `roms-tools` with conda to include all dependencies.""")
|
|
1138
|
+
|
|
1139
|
+
|
|
1140
|
+
def wrap_longitudes(ds: xr.Dataset, straddle: bool) -> xr.Dataset:
|
|
1141
|
+
"""
|
|
1142
|
+
Safely adjust longitude coordinates for datasets that may or may not cross
|
|
1143
|
+
the dateline. Only modifies longitude-like coordinates that are present.
|
|
1144
|
+
|
|
1145
|
+
Parameters
|
|
1146
|
+
----------
|
|
1147
|
+
ds : xr.Dataset
|
|
1148
|
+
Dataset containing longitude coordinates (e.g., lon_rho, lon_u, lon_v).
|
|
1149
|
+
straddle : bool
|
|
1150
|
+
- True: force longitudes into [-180, 180]
|
|
1151
|
+
- False: force longitudes into [0, 360]
|
|
1152
|
+
|
|
1153
|
+
Returns
|
|
1154
|
+
-------
|
|
1155
|
+
xr.Dataset
|
|
1156
|
+
A new dataset with adjusted longitude coordinates.
|
|
1157
|
+
"""
|
|
1158
|
+
lon_coords = ["lon_rho", "lon_u", "lon_v"]
|
|
1159
|
+
|
|
1160
|
+
for lon_name in lon_coords:
|
|
1161
|
+
if lon_name not in ds.coords:
|
|
1162
|
+
continue # skip missing coordinate
|
|
1163
|
+
|
|
1164
|
+
lon = ds.coords[lon_name]
|
|
1165
|
+
|
|
1166
|
+
if straddle:
|
|
1167
|
+
# wrap into [-180, 180]
|
|
1168
|
+
lon_wrapped = xr.where(lon > 180, lon - 360, lon)
|
|
1169
|
+
else:
|
|
1170
|
+
# wrap into [0, 360]
|
|
1171
|
+
lon_wrapped = xr.where(lon < 0, lon + 360, lon)
|
|
1172
|
+
|
|
1173
|
+
# preserve attributes
|
|
1174
|
+
lon_wrapped.attrs = lon.attrs.copy()
|
|
1175
|
+
|
|
1176
|
+
# reassign explicitly as a coordinate
|
|
1177
|
+
ds = ds.assign_coords({lon_name: lon_wrapped})
|
|
1178
|
+
|
|
1179
|
+
return ds
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
def interpolate_from_climatology(
|
|
1183
|
+
field: xr.DataArray | xr.Dataset,
|
|
1184
|
+
time_dim: str,
|
|
1185
|
+
time_coord: str,
|
|
1186
|
+
time: xr.DataArray | pd.DatetimeIndex,
|
|
1187
|
+
) -> xr.DataArray | xr.Dataset:
|
|
1188
|
+
"""Interpolates a climatological field to specified time points.
|
|
1189
|
+
|
|
1190
|
+
This function interpolates the input `field` based on `day_of_year` values
|
|
1191
|
+
extracted from the provided `time` points. If `field` is an `xarray.Dataset`,
|
|
1192
|
+
interpolation is applied to all its data variables individually.
|
|
1193
|
+
|
|
1194
|
+
Parameters
|
|
1195
|
+
----------
|
|
1196
|
+
field : xarray.DataArray or xarray.Dataset
|
|
1197
|
+
The input field to be interpolated.
|
|
1198
|
+
- If `field` is an `xarray.DataArray`, it must have a time dimension identified by `time_dim_name`.
|
|
1199
|
+
- If `field` is an `xarray.Dataset`, all variables within the dataset are interpolated along `time_dim_name`.
|
|
1200
|
+
The time dimension is assumed to represent `day_of_year` for climatological purposes.
|
|
1201
|
+
time_dim : str
|
|
1202
|
+
The name of the time dimension in `field`.
|
|
1203
|
+
time_coord : str
|
|
1204
|
+
The name of the time coordinate in `field`.
|
|
1205
|
+
time : xarray.DataArray or pandas.DatetimeIndex
|
|
1206
|
+
The target time points for interpolation. These are internally converted to `day_of_year`
|
|
1207
|
+
before performing interpolation.
|
|
1208
|
+
|
|
1209
|
+
Returns
|
|
1210
|
+
-------
|
|
1211
|
+
xarray.DataArray or xarray.Dataset
|
|
1212
|
+
The interpolated field, maintaining the same type (`xarray.DataArray` or `xarray.Dataset`)
|
|
1213
|
+
but aligned to the specified `time` values.
|
|
1214
|
+
|
|
1215
|
+
Notes
|
|
1216
|
+
-----
|
|
1217
|
+
- This function assumes that `field` represents a climatological dataset, where time is expressed as `day_of_year` (1-365).
|
|
1218
|
+
- The `time` input is automatically converted to `day_of_year`, so manual conversion is not required before calling this function.
|
|
1219
|
+
"""
|
|
1220
|
+
|
|
1221
|
+
def np_times_to_fractional_days(
|
|
1222
|
+
np_times: np.ndarray | pd.DatetimeIndex | np.datetime64 | pd.Timestamp,
|
|
1223
|
+
) -> np.ndarray:
|
|
1224
|
+
"""Convert datetime(s) to fractional day-of-year values."""
|
|
1225
|
+
pd_times = pd.to_datetime(np_times)
|
|
1226
|
+
|
|
1227
|
+
# scalar input -> make it a 1-element array
|
|
1228
|
+
if np.isscalar(pd_times):
|
|
1229
|
+
pd_times = np.array([pd_times])
|
|
1230
|
+
|
|
1231
|
+
fractional_days = pd_times.dayofyear + (
|
|
1232
|
+
pd_times.hour / 24 + pd_times.minute / 1440 + pd_times.second / 86400
|
|
1233
|
+
)
|
|
1234
|
+
return (
|
|
1235
|
+
fractional_days.values
|
|
1236
|
+
if hasattr(fractional_days, "values")
|
|
1237
|
+
else np.array(fractional_days)
|
|
1238
|
+
)
|
|
1239
|
+
|
|
1240
|
+
def interpolate_single_field(data_array: xr.DataArray) -> xr.DataArray:
|
|
1241
|
+
if isinstance(time, xr.DataArray):
|
|
1242
|
+
day_of_year = time.dt.dayofyear
|
|
1243
|
+
else:
|
|
1244
|
+
day_of_year = np_times_to_fractional_days(time)
|
|
1245
|
+
|
|
1246
|
+
data_array_interpolated = interpolate_cyclic_time(
|
|
1247
|
+
data_array, time_dim, time_coord, day_of_year
|
|
1248
|
+
)
|
|
1249
|
+
|
|
1250
|
+
# expand dims if single element
|
|
1251
|
+
if day_of_year.size == 1:
|
|
1252
|
+
data_array_interpolated = data_array_interpolated.expand_dims({time_dim: 1})
|
|
1253
|
+
return data_array_interpolated
|
|
1254
|
+
|
|
1255
|
+
if isinstance(field, xr.DataArray):
|
|
1256
|
+
return interpolate_single_field(field)
|
|
1257
|
+
elif isinstance(field, xr.Dataset):
|
|
1258
|
+
interpolated_data_vars = {
|
|
1259
|
+
var: interpolate_single_field(data_array)
|
|
1260
|
+
for var, data_array in field.data_vars.items()
|
|
1261
|
+
}
|
|
1262
|
+
return xr.Dataset(interpolated_data_vars, attrs=field.attrs)
|
|
1263
|
+
|
|
1264
|
+
else:
|
|
1265
|
+
raise TypeError("Input 'field' must be an xarray.DataArray or xarray.Dataset.")
|
|
1266
|
+
|
|
1267
|
+
|
|
1268
|
+
def interpolate_cyclic_time(
|
|
1269
|
+
data_array: xr.DataArray,
|
|
1270
|
+
time_dim: str,
|
|
1271
|
+
time_coord: str,
|
|
1272
|
+
day_of_year: int | float | np.ndarray | xr.DataArray | Sequence[int | float],
|
|
1273
|
+
) -> xr.DataArray:
|
|
1274
|
+
"""Interpolates a DataArray cyclically across the start and end of the year.
|
|
1275
|
+
|
|
1276
|
+
This function extends the data cyclically by appending the last time step
|
|
1277
|
+
(shifted back by one year) at the beginning and the first time step
|
|
1278
|
+
(shifted forward by one year) at the end. It then performs linear interpolation
|
|
1279
|
+
to match the specified `day_of_year` values.
|
|
1280
|
+
|
|
1281
|
+
Parameters
|
|
1282
|
+
----------
|
|
1283
|
+
data_array : xr.DataArray
|
|
1284
|
+
The input data array containing a time-like dimension.
|
|
1285
|
+
time_dim : str
|
|
1286
|
+
The name of the time dimension in the dataset.
|
|
1287
|
+
time_coord : str
|
|
1288
|
+
The name of the time coordinate in the dataset.
|
|
1289
|
+
day_of_year : Union[int, float, np.ndarray, xr.DataArray, Sequence[Union[int, float]]]
|
|
1290
|
+
The target day(s) of the year for interpolation. This can be:
|
|
1291
|
+
- A single integer or float representing the day of the year.
|
|
1292
|
+
- A NumPy array or xarray DataArray containing multiple days.
|
|
1293
|
+
- A list or tuple of integers or floats for multiple target days.
|
|
1294
|
+
|
|
1295
|
+
Returns
|
|
1296
|
+
-------
|
|
1297
|
+
xr.DataArray
|
|
1298
|
+
The interpolated DataArray, ensuring cyclic continuity across year boundaries.
|
|
1299
|
+
|
|
1300
|
+
Notes
|
|
1301
|
+
-----
|
|
1302
|
+
- This function is useful for interpolating climatological data, where the time axis
|
|
1303
|
+
represents a repeating annual cycle.
|
|
1304
|
+
- The `day_of_year` values should be within the range [1, 365] or [1, 366] for leap years.
|
|
1305
|
+
"""
|
|
1306
|
+
# Concatenate across the beginning and end of the year
|
|
1307
|
+
time_concat = xr.concat(
|
|
1308
|
+
[
|
|
1309
|
+
data_array[time_coord][-1] - 365.25, # Shift last time backward
|
|
1310
|
+
data_array[time_coord],
|
|
1311
|
+
data_array[time_coord][0] + 365.25, # Shift first time forward
|
|
1312
|
+
],
|
|
1313
|
+
dim=time_dim,
|
|
1314
|
+
)
|
|
1315
|
+
|
|
1316
|
+
data_array_concat = xr.concat(
|
|
1317
|
+
[
|
|
1318
|
+
data_array.isel(**{time_dim: -1}), # Append last value at the beginning
|
|
1319
|
+
data_array,
|
|
1320
|
+
data_array.isel(**{time_dim: 0}), # Append first value at the end
|
|
1321
|
+
],
|
|
1322
|
+
dim=time_dim,
|
|
1323
|
+
)
|
|
1324
|
+
data_array_concat[time_dim] = time_concat
|
|
1325
|
+
|
|
1326
|
+
# Interpolate to specified times
|
|
1327
|
+
data_array_interpolated = data_array_concat.interp(
|
|
1328
|
+
**{time_dim: day_of_year}, method="linear"
|
|
1329
|
+
)
|
|
1330
|
+
|
|
1331
|
+
return data_array_interpolated
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: roms-tools
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.5.0
|
|
4
4
|
Summary: Tools for running and analysing UCLA-ROMS simulations
|
|
5
5
|
Author-email: Nora Loose <nora.loose@gmail.com>, Thomas Nicholas <tom@cworthy.org>, Scott Eilerman <scott.eilerman@cworthy.org>
|
|
6
6
|
License: Apache-2
|
|
@@ -64,7 +64,7 @@ Dynamic: license-file
|
|
|
64
64
|
|
|
65
65
|
## Overview
|
|
66
66
|
|
|
67
|
-
A suite of Python tools for setting up and analyzing a [UCLA-ROMS](https://github.com/
|
|
67
|
+
A suite of Python tools for setting up and analyzing a [UCLA-ROMS](https://github.com/CWorthy-ocean/ucla-roms) simulation with or without [MARBL biogeochemistry](https://marbl-ecosys.github.io/versions/latest_release/index.html).
|
|
68
68
|
|
|
69
69
|
## Installation
|
|
70
70
|
|
|
@@ -152,5 +152,4 @@ We also accept contributions in the form of Pull Requests.
|
|
|
152
152
|
|
|
153
153
|
## See also
|
|
154
154
|
|
|
155
|
-
- [ROMS source code](https://github.com/CESR-lab/ucla-roms)
|
|
156
155
|
- [C-Star](https://github.com/CWorthy-ocean/C-Star)
|