roms-tools 3.1.2__py3-none-any.whl → 3.3.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 +3 -0
- roms_tools/analysis/cdr_analysis.py +203 -0
- roms_tools/analysis/cdr_ensemble.py +198 -0
- roms_tools/analysis/roms_output.py +80 -46
- roms_tools/data/grids/GLORYS_global_grid.nc +0 -0
- roms_tools/download.py +4 -0
- roms_tools/plot.py +113 -51
- roms_tools/setup/boundary_forcing.py +45 -20
- roms_tools/setup/cdr_forcing.py +122 -8
- roms_tools/setup/cdr_release.py +161 -8
- roms_tools/setup/grid.py +150 -141
- roms_tools/setup/initial_conditions.py +113 -48
- roms_tools/setup/{datasets.py → lat_lon_datasets.py} +443 -938
- roms_tools/setup/mask.py +63 -7
- roms_tools/setup/nesting.py +314 -117
- roms_tools/setup/river_datasets.py +527 -0
- roms_tools/setup/river_forcing.py +46 -20
- roms_tools/setup/surface_forcing.py +7 -9
- roms_tools/setup/tides.py +2 -3
- roms_tools/setup/topography.py +8 -10
- roms_tools/setup/utils.py +396 -23
- roms_tools/tests/test_analysis/test_cdr_analysis.py +144 -0
- roms_tools/tests/test_analysis/test_cdr_ensemble.py +202 -0
- roms_tools/tests/test_analysis/test_roms_output.py +61 -3
- roms_tools/tests/test_setup/test_boundary_forcing.py +54 -52
- roms_tools/tests/test_setup/test_cdr_forcing.py +54 -0
- roms_tools/tests/test_setup/test_cdr_release.py +118 -1
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_north/c/0/0/0 +0 -0
- 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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_north/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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_north/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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_north/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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_north/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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_north/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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_north/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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_north/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/DOP_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_north/c/0/0/0 +0 -0
- 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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_north/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/Fe_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_north/c/0/0/0 +0 -0
- 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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_north/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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_north/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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_north/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/O2_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_north/c/0/0/0 +0 -0
- 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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_north/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/SiO3_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_north/c/0/0/0 +0 -0
- 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/diatC_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_north/c/0/0/0 +0 -0
- 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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_north/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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_north/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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_north/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/diatSi_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_north/c/0/0/0 +0 -0
- 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/diazC_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_north/c/0/0/0 +0 -0
- 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/diazChl_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_north/c/0/0/0 +0 -0
- 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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_north/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/diazP_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_north/c/0/0/0 +0 -0
- 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/spC_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_north/c/0/0/0 +0 -0
- 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/spCaCO3_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_north/c/0/0/0 +0 -0
- 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/spChl_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_north/c/0/0/0 +0 -0
- 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_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_north/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/spP_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_north/c/0/0/0 +0 -0
- 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/zarr.json +406 -406
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_north/c/0/0/0 +0 -0
- 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/boundary_forcing.zarr/salt_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_south/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_north/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_south/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zarr.json +182 -182
- roms_tools/tests/test_setup/test_data/grid.zarr/h/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/grid.zarr/zarr.json +191 -191
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/h/c/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/zarr.json +210 -210
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK_ALT_CO2/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC_ALT_CO2/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOCr/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DON/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DONr/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOP/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOPr/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Fe/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Lig/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NH4/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NO3/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/O2/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/PO4/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/SiO3/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatChl/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatFe/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatP/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatSi/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazChl/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazFe/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazP/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/salt/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spCaCO3/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spChl/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spFe/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spP/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/temp/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/u/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ubar/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/v/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/vbar/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zarr.json +182 -182
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zooC/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/salt/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/temp/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/u/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ubar/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/v/c/0/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/vbar/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/zarr.json +187 -187
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Im/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Re/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Im/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Re/c/0/0/0 +0 -0
- roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/zarr.json +66 -66
- roms_tools/tests/test_setup/test_grid.py +236 -115
- roms_tools/tests/test_setup/test_initial_conditions.py +94 -41
- roms_tools/tests/test_setup/{test_datasets.py → test_lat_lon_datasets.py} +409 -100
- roms_tools/tests/test_setup/test_nesting.py +119 -31
- roms_tools/tests/test_setup/test_river_datasets.py +48 -0
- roms_tools/tests/test_setup/test_surface_forcing.py +2 -1
- roms_tools/tests/test_setup/test_utils.py +92 -2
- roms_tools/tests/test_setup/utils.py +71 -0
- roms_tools/tests/test_tiling/test_join.py +241 -0
- roms_tools/tests/test_utils.py +139 -17
- roms_tools/tiling/join.py +189 -0
- roms_tools/utils.py +131 -99
- {roms_tools-3.1.2.dist-info → roms_tools-3.3.0.dist-info}/METADATA +12 -2
- {roms_tools-3.1.2.dist-info → roms_tools-3.3.0.dist-info}/RECORD +221 -211
- {roms_tools-3.1.2.dist-info → roms_tools-3.3.0.dist-info}/WHEEL +0 -0
- {roms_tools-3.1.2.dist-info → roms_tools-3.3.0.dist-info}/licenses/LICENSE +0 -0
- {roms_tools-3.1.2.dist-info → roms_tools-3.3.0.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from collections import OrderedDict
|
|
3
|
-
from datetime import datetime
|
|
3
|
+
from datetime import datetime, timedelta
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from unittest import mock
|
|
6
6
|
|
|
@@ -9,17 +9,27 @@ import pytest
|
|
|
9
9
|
import xarray as xr
|
|
10
10
|
|
|
11
11
|
from roms_tools.download import download_test_data
|
|
12
|
-
from roms_tools.setup.
|
|
12
|
+
from roms_tools.setup.lat_lon_datasets import (
|
|
13
|
+
GLORYS_GLOBAL_GRID_PATH,
|
|
13
14
|
CESMBGCDataset,
|
|
14
|
-
Dataset,
|
|
15
15
|
ERA5ARCODataset,
|
|
16
16
|
ERA5Correction,
|
|
17
17
|
GLORYSDataset,
|
|
18
18
|
GLORYSDefaultDataset,
|
|
19
|
-
|
|
19
|
+
LatLonDataset,
|
|
20
20
|
TPXODataset,
|
|
21
|
+
_concatenate_longitudes,
|
|
22
|
+
choose_subdomain,
|
|
23
|
+
get_glorys_bounds,
|
|
21
24
|
)
|
|
22
25
|
from roms_tools.setup.surface_forcing import DEFAULT_ERA5_ARCO_PATH
|
|
26
|
+
from roms_tools.setup.utils import get_target_coords
|
|
27
|
+
from roms_tools.tests.test_setup.utils import download_regional_and_bigger
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
import copernicusmarine # type: ignore
|
|
31
|
+
except ImportError:
|
|
32
|
+
copernicusmarine = None
|
|
23
33
|
|
|
24
34
|
|
|
25
35
|
@pytest.fixture
|
|
@@ -29,9 +39,9 @@ def global_dataset():
|
|
|
29
39
|
depth = np.linspace(0, 2000, 10)
|
|
30
40
|
time = [
|
|
31
41
|
np.datetime64("2022-01-01T00:00:00"),
|
|
32
|
-
np.datetime64("2022-
|
|
33
|
-
np.datetime64("2022-
|
|
34
|
-
np.datetime64("2022-
|
|
42
|
+
np.datetime64("2022-01-02T00:00:00"),
|
|
43
|
+
np.datetime64("2022-01-03T00:00:00"),
|
|
44
|
+
np.datetime64("2022-01-04T00:00:00"),
|
|
35
45
|
]
|
|
36
46
|
data = np.random.rand(4, 10, 180, 360)
|
|
37
47
|
ds = xr.Dataset(
|
|
@@ -52,9 +62,9 @@ def global_dataset_with_noon_times():
|
|
|
52
62
|
lat = np.linspace(-90, 90, 180)
|
|
53
63
|
time = [
|
|
54
64
|
np.datetime64("2022-01-01T12:00:00"),
|
|
55
|
-
np.datetime64("2022-
|
|
56
|
-
np.datetime64("2022-
|
|
57
|
-
np.datetime64("2022-
|
|
65
|
+
np.datetime64("2022-01-02T12:00:00"),
|
|
66
|
+
np.datetime64("2022-01-03T12:00:00"),
|
|
67
|
+
np.datetime64("2022-01-04T12:00:00"),
|
|
58
68
|
]
|
|
59
69
|
data = np.random.rand(4, 180, 360)
|
|
60
70
|
ds = xr.Dataset(
|
|
@@ -75,12 +85,12 @@ def global_dataset_with_multiple_times_per_day():
|
|
|
75
85
|
time = [
|
|
76
86
|
np.datetime64("2022-01-01T00:00:00"),
|
|
77
87
|
np.datetime64("2022-01-01T12:00:00"),
|
|
78
|
-
np.datetime64("2022-
|
|
79
|
-
np.datetime64("2022-
|
|
80
|
-
np.datetime64("2022-
|
|
81
|
-
np.datetime64("2022-
|
|
82
|
-
np.datetime64("2022-
|
|
83
|
-
np.datetime64("2022-
|
|
88
|
+
np.datetime64("2022-01-02T00:00:00"),
|
|
89
|
+
np.datetime64("2022-01-02T12:00:00"),
|
|
90
|
+
np.datetime64("2022-01-03T00:00:00"),
|
|
91
|
+
np.datetime64("2022-01-03T12:00:00"),
|
|
92
|
+
np.datetime64("2022-01-04T00:00:00"),
|
|
93
|
+
np.datetime64("2022-01-04T12:00:00"),
|
|
84
94
|
]
|
|
85
95
|
data = np.random.rand(8, 180, 360)
|
|
86
96
|
ds = xr.Dataset(
|
|
@@ -112,39 +122,42 @@ def non_global_dataset():
|
|
|
112
122
|
(
|
|
113
123
|
"global_dataset",
|
|
114
124
|
[
|
|
115
|
-
np.datetime64("2022-
|
|
116
|
-
np.datetime64("2022-
|
|
125
|
+
np.datetime64("2022-01-02T00:00:00"),
|
|
126
|
+
np.datetime64("2022-01-03T00:00:00"),
|
|
127
|
+
np.datetime64("2022-01-04T00:00:00"),
|
|
117
128
|
],
|
|
118
129
|
),
|
|
119
130
|
(
|
|
120
131
|
"global_dataset_with_noon_times",
|
|
121
132
|
[
|
|
122
133
|
np.datetime64("2022-01-01T12:00:00"),
|
|
123
|
-
np.datetime64("2022-
|
|
124
|
-
np.datetime64("2022-
|
|
134
|
+
np.datetime64("2022-01-02T12:00:00"),
|
|
135
|
+
np.datetime64("2022-01-03T12:00:00"),
|
|
136
|
+
np.datetime64("2022-01-04T12:00:00"),
|
|
125
137
|
],
|
|
126
138
|
),
|
|
127
139
|
(
|
|
128
140
|
"global_dataset_with_multiple_times_per_day",
|
|
129
141
|
[
|
|
130
|
-
np.datetime64("2022-
|
|
131
|
-
np.datetime64("2022-
|
|
132
|
-
np.datetime64("2022-
|
|
142
|
+
np.datetime64("2022-01-02T00:00:00"),
|
|
143
|
+
np.datetime64("2022-01-02T12:00:00"),
|
|
144
|
+
np.datetime64("2022-01-03T00:00:00"),
|
|
145
|
+
np.datetime64("2022-01-03T12:00:00"),
|
|
146
|
+
np.datetime64("2022-01-04T00:00:00"),
|
|
133
147
|
],
|
|
134
148
|
),
|
|
135
149
|
],
|
|
136
150
|
)
|
|
137
151
|
def test_select_times(data_fixture, expected_time_values, request, tmp_path, use_dask):
|
|
138
152
|
"""Test selecting times with different datasets."""
|
|
139
|
-
start_time = datetime(2022,
|
|
140
|
-
end_time = datetime(2022,
|
|
153
|
+
start_time = datetime(2022, 1, 2)
|
|
154
|
+
end_time = datetime(2022, 1, 4)
|
|
141
155
|
|
|
142
|
-
# Get the fixture dynamically based on the parameter
|
|
143
156
|
dataset = request.getfixturevalue(data_fixture)
|
|
144
157
|
|
|
145
158
|
filepath = tmp_path / "test.nc"
|
|
146
159
|
dataset.to_netcdf(filepath)
|
|
147
|
-
dataset =
|
|
160
|
+
dataset = LatLonDataset(
|
|
148
161
|
filename=filepath,
|
|
149
162
|
var_names={"var": "var"},
|
|
150
163
|
start_time=start_time,
|
|
@@ -161,16 +174,15 @@ def test_select_times(data_fixture, expected_time_values, request, tmp_path, use
|
|
|
161
174
|
@pytest.mark.parametrize(
|
|
162
175
|
"data_fixture, expected_time_values",
|
|
163
176
|
[
|
|
164
|
-
("global_dataset", [np.datetime64("2022-
|
|
165
|
-
("global_dataset_with_noon_times", [np.datetime64("2022-
|
|
177
|
+
("global_dataset", [np.datetime64("2022-01-02T00:00:00")]),
|
|
178
|
+
("global_dataset_with_noon_times", [np.datetime64("2022-01-02T12:00:00")]),
|
|
166
179
|
],
|
|
167
180
|
)
|
|
168
181
|
def test_select_times_valid_start_no_end_time(
|
|
169
182
|
data_fixture, expected_time_values, request, tmp_path, use_dask
|
|
170
183
|
):
|
|
171
184
|
"""Test selecting times with only start_time specified."""
|
|
172
|
-
start_time = datetime(2022,
|
|
173
|
-
|
|
185
|
+
start_time = datetime(2022, 1, 2)
|
|
174
186
|
# Get the fixture dynamically based on the parameter
|
|
175
187
|
dataset = request.getfixturevalue(data_fixture)
|
|
176
188
|
|
|
@@ -179,14 +191,16 @@ def test_select_times_valid_start_no_end_time(
|
|
|
179
191
|
dataset.to_netcdf(filepath)
|
|
180
192
|
|
|
181
193
|
# Instantiate Dataset object using the temporary file
|
|
182
|
-
dataset =
|
|
194
|
+
dataset = LatLonDataset(
|
|
183
195
|
filename=filepath,
|
|
184
196
|
var_names={"var": "var"},
|
|
185
197
|
start_time=start_time,
|
|
186
198
|
use_dask=use_dask,
|
|
199
|
+
allow_flex_time=True,
|
|
187
200
|
)
|
|
188
201
|
|
|
189
202
|
assert dataset.ds is not None
|
|
203
|
+
assert "time" in dataset.ds.dims
|
|
190
204
|
assert len(dataset.ds.time) == len(expected_time_values)
|
|
191
205
|
for expected_time in expected_time_values:
|
|
192
206
|
assert expected_time in dataset.ds.time.values
|
|
@@ -212,9 +226,9 @@ def test_select_times_invalid_start_no_end_time(
|
|
|
212
226
|
|
|
213
227
|
with pytest.raises(
|
|
214
228
|
ValueError,
|
|
215
|
-
match="
|
|
229
|
+
match="No exact match found ",
|
|
216
230
|
):
|
|
217
|
-
dataset =
|
|
231
|
+
dataset = LatLonDataset(
|
|
218
232
|
filename=filepath,
|
|
219
233
|
var_names={"var": "var"},
|
|
220
234
|
start_time=datetime(2022, 5, 1),
|
|
@@ -230,14 +244,15 @@ def test_multiple_matching_times(
|
|
|
230
244
|
"""
|
|
231
245
|
filepath = tmp_path / "test.nc"
|
|
232
246
|
global_dataset_with_multiple_times_per_day.to_netcdf(filepath)
|
|
233
|
-
dataset =
|
|
247
|
+
dataset = LatLonDataset(
|
|
234
248
|
filename=filepath,
|
|
235
249
|
var_names={"var": "var"},
|
|
236
|
-
start_time=datetime(
|
|
250
|
+
start_time=datetime(2021, 12, 31, 22, 0),
|
|
237
251
|
use_dask=use_dask,
|
|
252
|
+
allow_flex_time=True,
|
|
238
253
|
)
|
|
239
254
|
|
|
240
|
-
assert dataset.ds["time"].values == np.datetime64(datetime(2022,
|
|
255
|
+
assert dataset.ds["time"].values == np.datetime64(datetime(2022, 1, 1, 0, 0))
|
|
241
256
|
|
|
242
257
|
|
|
243
258
|
def test_warnings_times(global_dataset, tmp_path, caplog, use_dask):
|
|
@@ -249,7 +264,7 @@ def test_warnings_times(global_dataset, tmp_path, caplog, use_dask):
|
|
|
249
264
|
start_time = datetime(2021, 1, 1)
|
|
250
265
|
end_time = datetime(2021, 2, 1)
|
|
251
266
|
|
|
252
|
-
|
|
267
|
+
LatLonDataset(
|
|
253
268
|
filename=filepath,
|
|
254
269
|
var_names={"var": "var"},
|
|
255
270
|
start_time=start_time,
|
|
@@ -257,13 +272,13 @@ def test_warnings_times(global_dataset, tmp_path, caplog, use_dask):
|
|
|
257
272
|
use_dask=use_dask,
|
|
258
273
|
)
|
|
259
274
|
# Verify the warning message in the log
|
|
260
|
-
assert "No records found at or before the start_time
|
|
275
|
+
assert "No records found at or before the start_time" in caplog.text
|
|
261
276
|
|
|
262
277
|
with caplog.at_level(logging.WARNING):
|
|
263
278
|
start_time = datetime(2024, 1, 1)
|
|
264
279
|
end_time = datetime(2024, 2, 1)
|
|
265
280
|
|
|
266
|
-
|
|
281
|
+
LatLonDataset(
|
|
267
282
|
filename=filepath,
|
|
268
283
|
var_names={"var": "var"},
|
|
269
284
|
start_time=start_time,
|
|
@@ -271,17 +286,17 @@ def test_warnings_times(global_dataset, tmp_path, caplog, use_dask):
|
|
|
271
286
|
use_dask=use_dask,
|
|
272
287
|
)
|
|
273
288
|
# Verify the warning message in the log
|
|
274
|
-
assert "No records found at or after the end_time
|
|
289
|
+
assert "No records found at or after the end_time" in caplog.text
|
|
275
290
|
|
|
276
291
|
|
|
277
292
|
def test_from_ds(global_dataset, global_dataset_with_noon_times, use_dask, tmp_path):
|
|
278
|
-
"""Test the from_ds method of the
|
|
293
|
+
"""Test the from_ds method of the LatLonDataset class."""
|
|
279
294
|
start_time = datetime(2022, 1, 1)
|
|
280
295
|
|
|
281
296
|
filepath = tmp_path / "test.nc"
|
|
282
297
|
global_dataset.to_netcdf(filepath)
|
|
283
298
|
|
|
284
|
-
dataset =
|
|
299
|
+
dataset = LatLonDataset(
|
|
285
300
|
filename=filepath,
|
|
286
301
|
var_names={"var": "var"},
|
|
287
302
|
dim_names={
|
|
@@ -292,11 +307,12 @@ def test_from_ds(global_dataset, global_dataset_with_noon_times, use_dask, tmp_p
|
|
|
292
307
|
},
|
|
293
308
|
start_time=start_time,
|
|
294
309
|
use_dask=use_dask,
|
|
310
|
+
allow_flex_time=True,
|
|
295
311
|
)
|
|
296
312
|
|
|
297
|
-
new_dataset =
|
|
313
|
+
new_dataset = LatLonDataset.from_ds(dataset, global_dataset_with_noon_times)
|
|
298
314
|
|
|
299
|
-
assert isinstance(new_dataset,
|
|
315
|
+
assert isinstance(new_dataset, LatLonDataset)
|
|
300
316
|
assert new_dataset.ds.equals(
|
|
301
317
|
global_dataset_with_noon_times
|
|
302
318
|
) # Verify the new ds attribute is set correctly
|
|
@@ -313,7 +329,7 @@ def test_reverse_latitude_reverse_depth_choose_subdomain(
|
|
|
313
329
|
global_dataset, tmp_path, use_dask
|
|
314
330
|
):
|
|
315
331
|
"""Test reversing latitude when it is not ascending, the choose_subdomain method,
|
|
316
|
-
and the convert_to_negative_depth method of the
|
|
332
|
+
and the convert_to_negative_depth method of the LatLonDataset class.
|
|
317
333
|
"""
|
|
318
334
|
start_time = datetime(2022, 1, 1)
|
|
319
335
|
|
|
@@ -322,7 +338,7 @@ def test_reverse_latitude_reverse_depth_choose_subdomain(
|
|
|
322
338
|
global_dataset["depth"] = global_dataset["depth"][::-1]
|
|
323
339
|
global_dataset.to_netcdf(filepath)
|
|
324
340
|
|
|
325
|
-
dataset =
|
|
341
|
+
dataset = LatLonDataset(
|
|
326
342
|
filename=filepath,
|
|
327
343
|
var_names={"var": "var"},
|
|
328
344
|
dim_names={
|
|
@@ -333,6 +349,7 @@ def test_reverse_latitude_reverse_depth_choose_subdomain(
|
|
|
333
349
|
},
|
|
334
350
|
start_time=start_time,
|
|
335
351
|
use_dask=use_dask,
|
|
352
|
+
allow_flex_time=True,
|
|
336
353
|
)
|
|
337
354
|
|
|
338
355
|
assert np.all(np.diff(dataset.ds["latitude"]) > 0)
|
|
@@ -375,7 +392,9 @@ def test_reverse_latitude_reverse_depth_choose_subdomain(
|
|
|
375
392
|
def test_check_if_global_with_global_dataset(global_dataset, tmp_path, use_dask):
|
|
376
393
|
filepath = tmp_path / "test.nc"
|
|
377
394
|
global_dataset.to_netcdf(filepath)
|
|
378
|
-
dataset =
|
|
395
|
+
dataset = LatLonDataset(
|
|
396
|
+
filename=filepath, var_names={"var": "var"}, use_dask=use_dask
|
|
397
|
+
)
|
|
379
398
|
is_global = dataset.check_if_global(dataset.ds)
|
|
380
399
|
assert is_global
|
|
381
400
|
|
|
@@ -385,7 +404,9 @@ def test_check_if_global_with_non_global_dataset(
|
|
|
385
404
|
):
|
|
386
405
|
filepath = tmp_path / "test.nc"
|
|
387
406
|
non_global_dataset.to_netcdf(filepath)
|
|
388
|
-
dataset =
|
|
407
|
+
dataset = LatLonDataset(
|
|
408
|
+
filename=filepath, var_names={"var": "var"}, use_dask=use_dask
|
|
409
|
+
)
|
|
389
410
|
is_global = dataset.check_if_global(dataset.ds)
|
|
390
411
|
|
|
391
412
|
assert not is_global
|
|
@@ -403,7 +424,7 @@ def test_check_dataset(global_dataset, tmp_path, use_dask):
|
|
|
403
424
|
with pytest.raises(
|
|
404
425
|
ValueError, match="Dataset does not contain all required variables."
|
|
405
426
|
):
|
|
406
|
-
|
|
427
|
+
LatLonDataset(
|
|
407
428
|
filename=filepath,
|
|
408
429
|
var_names={"var": "var"},
|
|
409
430
|
start_time=start_time,
|
|
@@ -422,7 +443,7 @@ def test_check_dataset(global_dataset, tmp_path, use_dask):
|
|
|
422
443
|
with pytest.raises(
|
|
423
444
|
ValueError, match="Dataset does not contain all required dimensions."
|
|
424
445
|
):
|
|
425
|
-
|
|
446
|
+
LatLonDataset(
|
|
426
447
|
filename=filepath,
|
|
427
448
|
var_names={"var": "var"},
|
|
428
449
|
start_time=start_time,
|
|
@@ -431,12 +452,12 @@ def test_check_dataset(global_dataset, tmp_path, use_dask):
|
|
|
431
452
|
)
|
|
432
453
|
|
|
433
454
|
|
|
434
|
-
def
|
|
455
|
+
def test_era5_correction_match_subdomain(use_dask):
|
|
435
456
|
data = ERA5Correction(use_dask=use_dask)
|
|
436
457
|
lats = data.ds.latitude[10:20]
|
|
437
458
|
lons = data.ds.longitude[10:20]
|
|
438
459
|
target_coords = {"lat": lats, "lon": lons}
|
|
439
|
-
data.
|
|
460
|
+
data.match_subdomain(target_coords)
|
|
440
461
|
assert (data.ds["latitude"] == lats).all()
|
|
441
462
|
assert (data.ds["longitude"] == lons).all()
|
|
442
463
|
|
|
@@ -484,7 +505,7 @@ def test_default_glorys_dataset_loading_dask_not_installed() -> None:
|
|
|
484
505
|
|
|
485
506
|
with (
|
|
486
507
|
pytest.raises(RuntimeError),
|
|
487
|
-
mock.patch("roms_tools.utils.
|
|
508
|
+
mock.patch("roms_tools.utils.has_dask", return_value=False),
|
|
488
509
|
):
|
|
489
510
|
_ = GLORYSDefaultDataset(
|
|
490
511
|
filename=GLORYSDefaultDataset.dataset_name,
|
|
@@ -500,17 +521,51 @@ def test_default_glorys_dataset_loading_dask_not_installed() -> None:
|
|
|
500
521
|
def test_default_glorys_dataset_loading() -> None:
|
|
501
522
|
"""Verify the default GLORYS dataset is loaded correctly."""
|
|
502
523
|
start_time = datetime(2012, 1, 1)
|
|
503
|
-
end_time = datetime(2013, 1, 1)
|
|
504
524
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
525
|
+
for end_time in [start_time, start_time + timedelta(days=0.5)]:
|
|
526
|
+
data = GLORYSDefaultDataset(
|
|
527
|
+
filename=GLORYSDefaultDataset.dataset_name,
|
|
528
|
+
start_time=start_time,
|
|
529
|
+
end_time=end_time,
|
|
530
|
+
use_dask=True,
|
|
531
|
+
)
|
|
511
532
|
|
|
512
|
-
|
|
513
|
-
|
|
533
|
+
expected_vars = {"temp", "salt", "u", "v", "zeta"}
|
|
534
|
+
assert set(data.var_names).issuperset(expected_vars)
|
|
535
|
+
|
|
536
|
+
expected_vars = {"thetao", "so", "uo", "vo", "zos"}
|
|
537
|
+
assert "time" in data.ds.dims
|
|
538
|
+
assert set(data.ds.data_vars).issuperset(expected_vars)
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
@pytest.mark.parametrize(
|
|
542
|
+
"fname,start_time",
|
|
543
|
+
[
|
|
544
|
+
(download_test_data("GLORYS_NA_2012.nc"), datetime(2012, 1, 1, 12)),
|
|
545
|
+
(download_test_data("GLORYS_NA_20121231.nc"), datetime(2012, 12, 31, 12)),
|
|
546
|
+
(download_test_data("GLORYS_coarse_test_data.nc"), datetime(2021, 6, 29)),
|
|
547
|
+
],
|
|
548
|
+
)
|
|
549
|
+
@pytest.mark.parametrize("allow_flex_time", [True, False])
|
|
550
|
+
def test_non_default_glorys_dataset_loading(
|
|
551
|
+
fname, start_time, allow_flex_time, use_dask
|
|
552
|
+
) -> None:
|
|
553
|
+
"""Verify the default GLORYS dataset is loaded correctly."""
|
|
554
|
+
for end_time in [None, start_time, start_time]:
|
|
555
|
+
data = GLORYSDataset(
|
|
556
|
+
filename=fname,
|
|
557
|
+
start_time=start_time,
|
|
558
|
+
end_time=end_time,
|
|
559
|
+
use_dask=use_dask,
|
|
560
|
+
allow_flex_time=allow_flex_time,
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
expected_vars = {"temp", "salt", "u", "v", "zeta"}
|
|
564
|
+
assert set(data.var_names).issuperset(expected_vars)
|
|
565
|
+
|
|
566
|
+
expected_vars = {"thetao", "so", "uo", "vo", "zos"}
|
|
567
|
+
assert "time" in data.ds.dims
|
|
568
|
+
assert set(data.ds.data_vars).issuperset(expected_vars)
|
|
514
569
|
|
|
515
570
|
|
|
516
571
|
def test_data_concatenation(use_dask):
|
|
@@ -708,43 +763,297 @@ class TestTPXODataset:
|
|
|
708
763
|
global_tpxo_dataset.select_constituents(11, omega)
|
|
709
764
|
|
|
710
765
|
|
|
711
|
-
|
|
712
|
-
def test_deduplicate_river_names(self, tmp_path):
|
|
713
|
-
sample_dim_and_var_names = {
|
|
714
|
-
"dim_names": {"station": "station", "time": "time"},
|
|
715
|
-
"var_names": {
|
|
716
|
-
"latitude": "lat",
|
|
717
|
-
"longitude": "lon",
|
|
718
|
-
"flux": "flux",
|
|
719
|
-
"ratio": "ratio",
|
|
720
|
-
"name": "name",
|
|
721
|
-
},
|
|
722
|
-
}
|
|
766
|
+
# test _concatenate_longitudes
|
|
723
767
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
768
|
+
|
|
769
|
+
@pytest.fixture
|
|
770
|
+
def sample_ds(use_dask):
|
|
771
|
+
lon = xr.DataArray(np.array([0, 90, 180]), dims="lon", name="lon")
|
|
772
|
+
lat = xr.DataArray(np.array([-30, 0, 30]), dims="lat", name="lat")
|
|
773
|
+
|
|
774
|
+
var_with_lon = xr.DataArray(
|
|
775
|
+
np.arange(9).reshape(3, 3),
|
|
776
|
+
dims=("lat", "lon"),
|
|
777
|
+
coords={"lat": lat, "lon": lon},
|
|
778
|
+
name="var_with_lon",
|
|
779
|
+
)
|
|
780
|
+
|
|
781
|
+
var_no_lon = xr.DataArray(
|
|
782
|
+
np.array([1, 2, 3]),
|
|
783
|
+
dims="lat",
|
|
784
|
+
coords={"lat": lat},
|
|
785
|
+
name="var_no_lon",
|
|
786
|
+
)
|
|
787
|
+
|
|
788
|
+
ds = xr.Dataset({"var_with_lon": var_with_lon, "var_no_lon": var_no_lon})
|
|
789
|
+
|
|
790
|
+
if use_dask:
|
|
791
|
+
ds = ds.chunk({"lat": -1, "lon": -1})
|
|
792
|
+
|
|
793
|
+
return ds
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
@pytest.mark.parametrize(
|
|
797
|
+
"end,expected_lons",
|
|
798
|
+
[
|
|
799
|
+
("lower", [-360, -270, -180, 0, 90, 180]),
|
|
800
|
+
("upper", [0, 90, 180, 360, 450, 540]),
|
|
801
|
+
("both", [-360, -270, -180, 0, 90, 180, 360, 450, 540]),
|
|
802
|
+
],
|
|
803
|
+
)
|
|
804
|
+
def test_concatenate_longitudes(sample_ds, end, expected_lons, use_dask):
|
|
805
|
+
dim_names = {"longitude": "lon"}
|
|
806
|
+
|
|
807
|
+
ds_concat = _concatenate_longitudes(
|
|
808
|
+
sample_ds, dim_names, end=end, use_dask=use_dask
|
|
809
|
+
)
|
|
810
|
+
|
|
811
|
+
# longitude should be extended as expected
|
|
812
|
+
np.testing.assert_array_equal(ds_concat.lon.values, expected_lons)
|
|
813
|
+
|
|
814
|
+
# variable with longitude should be extended in size
|
|
815
|
+
assert ds_concat.var_with_lon.shape[-1] == len(expected_lons)
|
|
816
|
+
|
|
817
|
+
# variable without longitude should remain untouched
|
|
818
|
+
np.testing.assert_array_equal(
|
|
819
|
+
ds_concat.var_no_lon.values,
|
|
820
|
+
sample_ds.var_no_lon.values,
|
|
821
|
+
)
|
|
822
|
+
|
|
823
|
+
if use_dask:
|
|
824
|
+
import dask
|
|
825
|
+
|
|
826
|
+
# Ensure dask array backing the data
|
|
827
|
+
assert isinstance(ds_concat.var_with_lon.data, dask.array.Array)
|
|
828
|
+
# Longitude dimension should be chunked (-1 → one chunk spanning the whole dim)
|
|
829
|
+
assert ds_concat.var_with_lon.chunks[-1] == (len(expected_lons),)
|
|
830
|
+
else:
|
|
831
|
+
# With use_dask=False, data should be a numpy array
|
|
832
|
+
assert isinstance(ds_concat.var_with_lon.data, np.ndarray)
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
def test_invalid_end_raises(sample_ds):
|
|
836
|
+
dim_names = {"longitude": "lon"}
|
|
837
|
+
with pytest.raises(ValueError):
|
|
838
|
+
_concatenate_longitudes(sample_ds, dim_names, end="invalid")
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
# test choose_subdomain
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
def test_choose_subdomain_basic(global_dataset, use_dask):
|
|
845
|
+
target_coords = {
|
|
846
|
+
"lat": xr.DataArray([0, 10]),
|
|
847
|
+
"lon": xr.DataArray([30, 40]),
|
|
848
|
+
"straddle": False,
|
|
849
|
+
}
|
|
850
|
+
out = choose_subdomain(
|
|
851
|
+
global_dataset,
|
|
852
|
+
dim_names={"latitude": "latitude", "longitude": "longitude"},
|
|
853
|
+
resolution=1.0,
|
|
854
|
+
is_global=True,
|
|
855
|
+
target_coords=target_coords,
|
|
856
|
+
buffer_points=2,
|
|
857
|
+
use_dask=use_dask,
|
|
858
|
+
)
|
|
859
|
+
assert out.latitude.min() <= 0
|
|
860
|
+
assert out.latitude.max() >= 10
|
|
861
|
+
assert out.longitude.min() <= 30
|
|
862
|
+
assert out.longitude.max() >= 40
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
def test_choose_subdomain_raises_on_empty_lon(non_global_dataset, use_dask):
|
|
866
|
+
target_coords = {
|
|
867
|
+
"lat": xr.DataArray([-10, 10]),
|
|
868
|
+
"lon": xr.DataArray([210, 215]), # outside 0-180
|
|
869
|
+
"straddle": False,
|
|
870
|
+
}
|
|
871
|
+
with pytest.raises(ValueError, match="longitude range"):
|
|
872
|
+
choose_subdomain(
|
|
873
|
+
non_global_dataset,
|
|
874
|
+
dim_names={"latitude": "latitude", "longitude": "longitude"},
|
|
875
|
+
resolution=1.0,
|
|
876
|
+
is_global=False,
|
|
877
|
+
target_coords=target_coords,
|
|
878
|
+
use_dask=use_dask,
|
|
879
|
+
)
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
def test_choose_subdomain_raises_on_empty_lat(global_dataset, use_dask):
|
|
883
|
+
target_coords = {
|
|
884
|
+
"lat": xr.DataArray([1000, 1010]), # outside dataset range
|
|
885
|
+
"lon": xr.DataArray([30, 40]),
|
|
886
|
+
"straddle": False,
|
|
887
|
+
}
|
|
888
|
+
with pytest.raises(ValueError, match="latitude range"):
|
|
889
|
+
choose_subdomain(
|
|
890
|
+
global_dataset,
|
|
891
|
+
dim_names={"latitude": "latitude", "longitude": "longitude"},
|
|
892
|
+
resolution=1.0,
|
|
893
|
+
is_global=True,
|
|
894
|
+
target_coords=target_coords,
|
|
895
|
+
use_dask=use_dask,
|
|
744
896
|
)
|
|
745
897
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
898
|
+
|
|
899
|
+
def test_choose_subdomain_straddle(global_dataset, use_dask):
|
|
900
|
+
target_coords = {
|
|
901
|
+
"lat": xr.DataArray([-10, 10]),
|
|
902
|
+
"lon": xr.DataArray([-170, 170]), # cross the dateline
|
|
903
|
+
"straddle": True,
|
|
904
|
+
}
|
|
905
|
+
out = choose_subdomain(
|
|
906
|
+
global_dataset,
|
|
907
|
+
dim_names={"latitude": "latitude", "longitude": "longitude"},
|
|
908
|
+
resolution=1.0,
|
|
909
|
+
is_global=True,
|
|
910
|
+
target_coords=target_coords,
|
|
911
|
+
buffer_points=5,
|
|
912
|
+
use_dask=use_dask,
|
|
913
|
+
)
|
|
914
|
+
# Ensure output includes both sides of the dateline, mapped into -180 - 180
|
|
915
|
+
assert (out.longitude.min() < 0) and (out.longitude.max() > 0)
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
def test_choose_subdomain_wraps_negative_lon(global_dataset, use_dask):
|
|
919
|
+
target_coords = {
|
|
920
|
+
"lat": xr.DataArray([0, 20]),
|
|
921
|
+
"lon": xr.DataArray([-20, -10]), # negative longitudes
|
|
922
|
+
"straddle": False,
|
|
923
|
+
}
|
|
924
|
+
out = choose_subdomain(
|
|
925
|
+
global_dataset,
|
|
926
|
+
dim_names={"latitude": "latitude", "longitude": "longitude"},
|
|
927
|
+
resolution=1.0,
|
|
928
|
+
is_global=True,
|
|
929
|
+
target_coords=target_coords,
|
|
930
|
+
buffer_points=2,
|
|
931
|
+
use_dask=use_dask,
|
|
932
|
+
)
|
|
933
|
+
# Output longitudes should be shifted into [0, 360]
|
|
934
|
+
assert (out.longitude >= 0).all()
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
def test_choose_subdomain_respects_buffer(global_dataset, use_dask):
|
|
938
|
+
target_coords = {
|
|
939
|
+
"lat": xr.DataArray([0, 0]),
|
|
940
|
+
"lon": xr.DataArray([50, 50]),
|
|
941
|
+
"straddle": False,
|
|
942
|
+
}
|
|
943
|
+
out = choose_subdomain(
|
|
944
|
+
global_dataset,
|
|
945
|
+
dim_names={"latitude": "latitude", "longitude": "longitude"},
|
|
946
|
+
resolution=1.0,
|
|
947
|
+
is_global=True,
|
|
948
|
+
target_coords=target_coords,
|
|
949
|
+
buffer_points=10,
|
|
950
|
+
use_dask=use_dask,
|
|
951
|
+
)
|
|
952
|
+
# Buffer should extend at least 10 degrees beyond target lon
|
|
953
|
+
assert out.longitude.min() <= 40
|
|
954
|
+
assert out.longitude.max() >= 60
|
|
955
|
+
|
|
956
|
+
|
|
957
|
+
# test get_glorys_bounds
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
@pytest.fixture
|
|
961
|
+
def glorys_grid_0_360(tmp_path):
|
|
962
|
+
lats = np.linspace(-90, 90, 181)
|
|
963
|
+
lons = np.linspace(0, 360, 361)
|
|
964
|
+
ds = xr.Dataset(coords={"latitude": lats, "longitude": lons})
|
|
965
|
+
path = tmp_path / "GLORYS_0_360.nc"
|
|
966
|
+
ds.to_netcdf(path)
|
|
967
|
+
return path
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
@pytest.fixture
|
|
971
|
+
def glorys_grid_neg180_180(tmp_path):
|
|
972
|
+
lats = np.linspace(-90, 90, 181)
|
|
973
|
+
lons = np.linspace(-180, 180, 361)
|
|
974
|
+
ds = xr.Dataset(coords={"latitude": lats, "longitude": lons})
|
|
975
|
+
path = tmp_path / "GLORYS_neg180_180.nc"
|
|
976
|
+
ds.to_netcdf(path)
|
|
977
|
+
return path
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
@pytest.fixture
|
|
981
|
+
def glorys_grid_real():
|
|
982
|
+
return GLORYS_GLOBAL_GRID_PATH
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
@pytest.mark.parametrize(
|
|
986
|
+
"grid_fixture",
|
|
987
|
+
[
|
|
988
|
+
"grid",
|
|
989
|
+
"grid_that_straddles_dateline",
|
|
990
|
+
"grid_that_straddles_180_degree_meridian",
|
|
991
|
+
"small_grid",
|
|
992
|
+
"tiny_grid",
|
|
993
|
+
],
|
|
994
|
+
)
|
|
995
|
+
@pytest.mark.parametrize(
|
|
996
|
+
"glorys_grid_fixture",
|
|
997
|
+
["glorys_grid_0_360", "glorys_grid_neg180_180", "glorys_grid_real"],
|
|
998
|
+
)
|
|
999
|
+
def test_get_glorys_bounds(tmp_path, grid_fixture, glorys_grid_fixture, request):
|
|
1000
|
+
grid = request.getfixturevalue(grid_fixture)
|
|
1001
|
+
glorys_grid_path = request.getfixturevalue(glorys_grid_fixture)
|
|
1002
|
+
|
|
1003
|
+
bounds = get_glorys_bounds(grid=grid, glorys_grid_path=glorys_grid_path)
|
|
1004
|
+
assert set(bounds) == {
|
|
1005
|
+
"minimum_latitude",
|
|
1006
|
+
"maximum_latitude",
|
|
1007
|
+
"minimum_longitude",
|
|
1008
|
+
"maximum_longitude",
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
@pytest.mark.use_copernicus
|
|
1013
|
+
@pytest.mark.skipif(copernicusmarine is None, reason="copernicusmarine required")
|
|
1014
|
+
@pytest.mark.parametrize(
|
|
1015
|
+
"grid_fixture",
|
|
1016
|
+
[
|
|
1017
|
+
"tiny_grid_that_straddles_dateline",
|
|
1018
|
+
"tiny_grid_that_straddles_180_degree_meridian",
|
|
1019
|
+
"tiny_rotated_grid",
|
|
1020
|
+
],
|
|
1021
|
+
)
|
|
1022
|
+
def test_invariance_to_get_glorys_bounds(tmp_path, grid_fixture, use_dask, request):
|
|
1023
|
+
start_time = datetime(2012, 1, 1)
|
|
1024
|
+
grid = request.getfixturevalue(grid_fixture)
|
|
1025
|
+
target_coords = get_target_coords(grid)
|
|
1026
|
+
|
|
1027
|
+
regional_file, bigger_regional_file = download_regional_and_bigger(
|
|
1028
|
+
tmp_path, grid, start_time, variables=["thetao", "uo", "zos"]
|
|
1029
|
+
)
|
|
1030
|
+
|
|
1031
|
+
# create datasets from regional and bigger regional data
|
|
1032
|
+
regional_data = GLORYSDataset(
|
|
1033
|
+
var_names={"temp": "thetao", "u": "uo", "zeta": "zos"},
|
|
1034
|
+
filename=regional_file,
|
|
1035
|
+
start_time=start_time,
|
|
1036
|
+
climatology=False,
|
|
1037
|
+
allow_flex_time=False,
|
|
1038
|
+
use_dask=use_dask,
|
|
1039
|
+
)
|
|
1040
|
+
bigger_regional_data = GLORYSDataset(
|
|
1041
|
+
var_names={"temp": "thetao", "u": "uo", "zeta": "zos"},
|
|
1042
|
+
filename=bigger_regional_file,
|
|
1043
|
+
start_time=start_time,
|
|
1044
|
+
climatology=False,
|
|
1045
|
+
allow_flex_time=False,
|
|
1046
|
+
use_dask=use_dask,
|
|
1047
|
+
)
|
|
1048
|
+
|
|
1049
|
+
# subset both datasets and check they are the same
|
|
1050
|
+
regional_data.choose_subdomain(target_coords)
|
|
1051
|
+
bigger_regional_data.choose_subdomain(target_coords)
|
|
1052
|
+
|
|
1053
|
+
# Use assert_allclose instead of equals: necessary for grids that straddle the 180° meridian.
|
|
1054
|
+
# Copernicus returns data on [-180, 180] by default, but if you request a range
|
|
1055
|
+
# like [170, 190], it remaps longitudes. That remapping introduces tiny floating
|
|
1056
|
+
# point differences in the longitude coordinate, so strict equality will fail
|
|
1057
|
+
# even though the data are effectively identical.
|
|
1058
|
+
# For grids that do not straddle the 180° meridian, strict equality still holds.
|
|
1059
|
+
xr.testing.assert_allclose(bigger_regional_data.ds, regional_data.ds)
|