roms-tools 2.2.1__py3-none-any.whl → 2.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ci/environment.yml +1 -0
- roms_tools/__init__.py +2 -0
- roms_tools/analysis/roms_output.py +590 -0
- roms_tools/{setup/download.py → download.py} +3 -0
- roms_tools/{setup/plot.py → plot.py} +34 -28
- roms_tools/setup/boundary_forcing.py +199 -203
- roms_tools/setup/datasets.py +60 -136
- roms_tools/setup/grid.py +40 -67
- roms_tools/setup/initial_conditions.py +249 -247
- roms_tools/setup/nesting.py +6 -27
- roms_tools/setup/river_forcing.py +41 -76
- roms_tools/setup/surface_forcing.py +125 -75
- roms_tools/setup/tides.py +31 -51
- roms_tools/setup/topography.py +1 -1
- roms_tools/setup/utils.py +44 -224
- roms_tools/tests/test_analysis/test_roms_output.py +269 -0
- roms_tools/tests/{test_setup/test_regrid.py → test_regrid.py} +1 -1
- roms_tools/tests/test_setup/test_boundary_forcing.py +221 -58
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zattrs +5 -3
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zmetadata +156 -121
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/.zarray +2 -2
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/.zattrs +2 -1
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/bry_time/.zarray +2 -2
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/bry_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/bry_time/0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_north/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_south/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_north/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_north/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_north/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_west/.zarray +4 -4
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_west/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_west/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zattrs +4 -4
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zmetadata +4 -4
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/angle/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/angle_coarse/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/f/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/h/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_coarse/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_rho/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_u/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_v/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_coarse/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_rho/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_u/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_v/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_coarse/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_rho/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_u/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_v/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/pm/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/pn/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zattrs +2 -1
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zmetadata +6 -4
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Cs_r/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Cs_w/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NH4/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NO3/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/PO4/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/abs_time/.zattrs +1 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatSi/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ocean_time/.zattrs +1 -1
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spC/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spCaCO3/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spFe/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/temp/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/u/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ubar/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/v/0.0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/vbar/0.0.0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zmetadata +30 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_location/.zarray +22 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_location/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_location/0.0 +0 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/.zmetadata +30 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_location/.zarray +22 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_location/.zattrs +8 -0
- roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_location/0.0 +0 -0
- roms_tools/tests/test_setup/test_datasets.py +1 -1
- roms_tools/tests/test_setup/test_grid.py +1 -14
- roms_tools/tests/test_setup/test_initial_conditions.py +205 -67
- roms_tools/tests/test_setup/test_nesting.py +0 -16
- roms_tools/tests/test_setup/test_river_forcing.py +9 -37
- roms_tools/tests/test_setup/test_surface_forcing.py +103 -74
- roms_tools/tests/test_setup/test_tides.py +5 -17
- roms_tools/tests/test_setup/test_topography.py +1 -1
- roms_tools/tests/test_setup/test_utils.py +57 -1
- roms_tools/tests/{test_utils.py → test_tiling/test_partition.py} +1 -1
- roms_tools/tiling/partition.py +338 -0
- roms_tools/utils.py +310 -276
- roms_tools/vertical_coordinate.py +227 -0
- {roms_tools-2.2.1.dist-info → roms_tools-2.4.0.dist-info}/METADATA +1 -1
- {roms_tools-2.2.1.dist-info → roms_tools-2.4.0.dist-info}/RECORD +151 -142
- roms_tools/setup/vertical_coordinate.py +0 -109
- /roms_tools/{setup/regrid.py → regrid.py} +0 -0
- {roms_tools-2.2.1.dist-info → roms_tools-2.4.0.dist-info}/LICENSE +0 -0
- {roms_tools-2.2.1.dist-info → roms_tools-2.4.0.dist-info}/WHEEL +0 -0
- {roms_tools-2.2.1.dist-info → roms_tools-2.4.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import xarray as xr
|
|
4
|
+
import os
|
|
5
|
+
import logging
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from roms_tools import Grid, ROMSOutput
|
|
8
|
+
from roms_tools.download import download_test_data
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.fixture
|
|
12
|
+
def roms_output_from_restart_file(use_dask):
|
|
13
|
+
|
|
14
|
+
fname_grid = Path(download_test_data("epac25km_grd.nc"))
|
|
15
|
+
grid = Grid.from_file(fname_grid)
|
|
16
|
+
|
|
17
|
+
# Single file
|
|
18
|
+
return ROMSOutput(
|
|
19
|
+
grid=grid,
|
|
20
|
+
path=Path(download_test_data("eastpac25km_rst.19980106000000.nc")),
|
|
21
|
+
type="restart",
|
|
22
|
+
use_dask=use_dask,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_load_model_output_file(roms_output_from_restart_file, use_dask):
|
|
27
|
+
|
|
28
|
+
assert isinstance(roms_output_from_restart_file.ds, xr.Dataset)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_load_model_output_directory(use_dask):
|
|
32
|
+
fname_grid = Path(download_test_data("epac25km_grd.nc"))
|
|
33
|
+
grid = Grid.from_file(fname_grid)
|
|
34
|
+
|
|
35
|
+
# Download at least two files, so these will be found within the pooch directory
|
|
36
|
+
_ = Path(download_test_data("eastpac25km_rst.19980106000000.nc"))
|
|
37
|
+
_ = Path(download_test_data("eastpac25km_rst.19980126000000.nc"))
|
|
38
|
+
|
|
39
|
+
# Directory
|
|
40
|
+
directory = os.path.dirname(download_test_data("eastpac25km_rst.19980106000000.nc"))
|
|
41
|
+
output = ROMSOutput(grid=grid, path=directory, type="restart", use_dask=use_dask)
|
|
42
|
+
assert isinstance(output.ds, xr.Dataset)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_load_model_output_file_list(use_dask):
|
|
46
|
+
fname_grid = Path(download_test_data("epac25km_grd.nc"))
|
|
47
|
+
grid = Grid.from_file(fname_grid)
|
|
48
|
+
|
|
49
|
+
# List of files
|
|
50
|
+
file1 = Path(download_test_data("eastpac25km_rst.19980106000000.nc"))
|
|
51
|
+
file2 = Path(download_test_data("eastpac25km_rst.19980126000000.nc"))
|
|
52
|
+
output = ROMSOutput(
|
|
53
|
+
grid=grid, path=[file1, file2], type="restart", use_dask=use_dask
|
|
54
|
+
)
|
|
55
|
+
assert isinstance(output.ds, xr.Dataset)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_invalid_type(use_dask):
|
|
59
|
+
fname_grid = Path(download_test_data("epac25km_grd.nc"))
|
|
60
|
+
grid = Grid.from_file(fname_grid)
|
|
61
|
+
|
|
62
|
+
# Invalid type
|
|
63
|
+
with pytest.raises(ValueError, match="Invalid type 'invalid_type'"):
|
|
64
|
+
ROMSOutput(
|
|
65
|
+
grid=grid,
|
|
66
|
+
path=Path(download_test_data("eastpac25km_rst.19980106000000.nc")),
|
|
67
|
+
type="invalid_type",
|
|
68
|
+
use_dask=use_dask,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_invalid_path(use_dask):
|
|
73
|
+
fname_grid = Path(download_test_data("epac25km_grd.nc"))
|
|
74
|
+
grid = Grid.from_file(fname_grid)
|
|
75
|
+
|
|
76
|
+
# Non-existent file
|
|
77
|
+
with pytest.raises(FileNotFoundError):
|
|
78
|
+
ROMSOutput(
|
|
79
|
+
grid=grid,
|
|
80
|
+
path=Path("/path/to/nonexistent/file.nc"),
|
|
81
|
+
type="restart",
|
|
82
|
+
use_dask=use_dask,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Non-existent directory
|
|
86
|
+
with pytest.raises(FileNotFoundError):
|
|
87
|
+
ROMSOutput(
|
|
88
|
+
grid=grid,
|
|
89
|
+
path=Path("/path/to/nonexistent/directory"),
|
|
90
|
+
type="restart",
|
|
91
|
+
use_dask=use_dask,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def test_set_correct_model_reference_date(use_dask):
|
|
96
|
+
fname_grid = Path(download_test_data("epac25km_grd.nc"))
|
|
97
|
+
grid = Grid.from_file(fname_grid)
|
|
98
|
+
|
|
99
|
+
output = ROMSOutput(
|
|
100
|
+
grid=grid,
|
|
101
|
+
path=Path(download_test_data("eastpac25km_rst.19980106000000.nc")),
|
|
102
|
+
type="restart",
|
|
103
|
+
use_dask=use_dask,
|
|
104
|
+
)
|
|
105
|
+
assert output.model_reference_date == datetime(1995, 1, 1)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def test_model_reference_date_mismatch(use_dask):
|
|
109
|
+
fname_grid = Path(download_test_data("epac25km_grd.nc"))
|
|
110
|
+
grid = Grid.from_file(fname_grid)
|
|
111
|
+
|
|
112
|
+
# Create a ROMSOutput with a specified model_reference_date
|
|
113
|
+
model_ref_date = datetime(2020, 1, 1)
|
|
114
|
+
with pytest.raises(
|
|
115
|
+
ValueError, match="Mismatch between `self.model_reference_date`"
|
|
116
|
+
):
|
|
117
|
+
ROMSOutput(
|
|
118
|
+
grid=grid,
|
|
119
|
+
path=Path(download_test_data("eastpac25km_rst.19980106000000.nc")),
|
|
120
|
+
type="restart",
|
|
121
|
+
model_reference_date=model_ref_date,
|
|
122
|
+
use_dask=use_dask,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def test_model_reference_date_no_metadata(use_dask, tmp_path, caplog):
|
|
127
|
+
# Helper function to handle the test logic for cases where metadata is missing or invalid
|
|
128
|
+
def test_no_metadata(faulty_ocean_time_attr, expected_exception, log_message=None):
|
|
129
|
+
ds = xr.open_dataset(fname)
|
|
130
|
+
ds["ocean_time"].attrs = faulty_ocean_time_attr
|
|
131
|
+
|
|
132
|
+
# Write modified dataset to a new file
|
|
133
|
+
fname_mod = tmp_path / "eastpac25km_rst.19980106000000_without_metadata.nc"
|
|
134
|
+
ds.to_netcdf(fname_mod)
|
|
135
|
+
|
|
136
|
+
# Test case 1: Expecting a ValueError when metadata is missing or invalid
|
|
137
|
+
with pytest.raises(
|
|
138
|
+
expected_exception,
|
|
139
|
+
match="Model reference date could not be inferred from the metadata",
|
|
140
|
+
):
|
|
141
|
+
ROMSOutput(grid=grid, path=fname_mod, type="restart", use_dask=use_dask)
|
|
142
|
+
|
|
143
|
+
# Test case 2: When a model reference date is explicitly set, verify the warning
|
|
144
|
+
with caplog.at_level(logging.WARNING):
|
|
145
|
+
ROMSOutput(
|
|
146
|
+
grid=grid,
|
|
147
|
+
path=fname_mod,
|
|
148
|
+
model_reference_date=datetime(1995, 1, 1),
|
|
149
|
+
type="restart",
|
|
150
|
+
use_dask=use_dask,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
if log_message:
|
|
154
|
+
# Verify the warning message in the log
|
|
155
|
+
assert log_message in caplog.text
|
|
156
|
+
|
|
157
|
+
fname_mod.unlink()
|
|
158
|
+
|
|
159
|
+
# Load grid and test data
|
|
160
|
+
fname_grid = Path(download_test_data("epac25km_grd.nc"))
|
|
161
|
+
grid = Grid.from_file(fname_grid)
|
|
162
|
+
fname = download_test_data("eastpac25km_rst.19980106000000.nc")
|
|
163
|
+
|
|
164
|
+
# Test 1: Ocean time attribute 'long_name' is missing
|
|
165
|
+
test_no_metadata({}, ValueError)
|
|
166
|
+
|
|
167
|
+
# Test 2: Ocean time attribute 'long_name' contains invalid information
|
|
168
|
+
test_no_metadata(
|
|
169
|
+
{"long_name": "some random text"},
|
|
170
|
+
ValueError,
|
|
171
|
+
"Could not infer the model reference date from the metadata.",
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def test_compute_depth_coordinates(use_dask):
|
|
176
|
+
fname_grid = Path(download_test_data("epac25km_grd.nc"))
|
|
177
|
+
grid = Grid.from_file(fname_grid)
|
|
178
|
+
|
|
179
|
+
fname_restart1 = Path(download_test_data("eastpac25km_rst.19980106000000.nc"))
|
|
180
|
+
output = ROMSOutput(
|
|
181
|
+
grid=grid, path=fname_restart1, type="restart", use_dask=use_dask
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# Before calling get_vertical_coordinates, check if the dataset doesn't already have depth coordinates
|
|
185
|
+
assert "layer_depth_rho" not in output.ds.data_vars
|
|
186
|
+
|
|
187
|
+
# Call the method to get vertical coordinates
|
|
188
|
+
output.compute_depth_coordinates(depth_type="layer")
|
|
189
|
+
|
|
190
|
+
# Check if the depth coordinates were added
|
|
191
|
+
assert "layer_depth_rho" in output.ds.data_vars
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def test_check_vertical_coordinate_mismatch(use_dask):
|
|
195
|
+
fname_grid = Path(download_test_data("epac25km_grd.nc"))
|
|
196
|
+
grid = Grid.from_file(fname_grid)
|
|
197
|
+
|
|
198
|
+
fname_restart1 = Path(download_test_data("eastpac25km_rst.19980106000000.nc"))
|
|
199
|
+
output = ROMSOutput(
|
|
200
|
+
grid=grid, path=fname_restart1, type="restart", use_dask=use_dask
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# create a mock dataset with inconsistent vertical coordinate parameters
|
|
204
|
+
ds_mock = output.ds.copy()
|
|
205
|
+
|
|
206
|
+
# Modify one of the vertical coordinate attributes to cause a mismatch
|
|
207
|
+
ds_mock.attrs["theta_s"] = 999
|
|
208
|
+
|
|
209
|
+
# Check if ValueError is raised due to mismatch
|
|
210
|
+
with pytest.raises(ValueError, match="theta_s from grid"):
|
|
211
|
+
output._check_vertical_coordinate(ds_mock)
|
|
212
|
+
|
|
213
|
+
# create a mock dataset with inconsistent vertical coordinate parameters
|
|
214
|
+
ds_mock = output.ds.copy()
|
|
215
|
+
|
|
216
|
+
# Modify one of the vertical coordinate attributes to cause a mismatch
|
|
217
|
+
ds_mock.attrs["Cs_w"] = ds_mock.attrs["Cs_w"] + 0.01
|
|
218
|
+
|
|
219
|
+
# Check if ValueError is raised due to mismatch
|
|
220
|
+
with pytest.raises(ValueError, match="Cs_w from grid"):
|
|
221
|
+
output._check_vertical_coordinate(ds_mock)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def test_that_coordinates_are_added(use_dask):
|
|
225
|
+
fname_grid = Path(download_test_data("epac25km_grd.nc"))
|
|
226
|
+
grid = Grid.from_file(fname_grid)
|
|
227
|
+
|
|
228
|
+
fname_restart1 = Path(download_test_data("eastpac25km_rst.19980106000000.nc"))
|
|
229
|
+
output = ROMSOutput(
|
|
230
|
+
grid=grid, path=fname_restart1, type="restart", use_dask=use_dask
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
assert "abs_time" in output.ds.coords
|
|
234
|
+
assert "lat_rho" in output.ds.coords
|
|
235
|
+
assert "lon_rho" in output.ds.coords
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def test_plot(roms_output_from_restart_file, use_dask):
|
|
239
|
+
|
|
240
|
+
kwargs = {}
|
|
241
|
+
for var_name in ["temp", "u", "v"]:
|
|
242
|
+
roms_output_from_restart_file.plot(var_name, time=0, s=-1, **kwargs)
|
|
243
|
+
roms_output_from_restart_file.plot(var_name, time=0, eta=0, **kwargs)
|
|
244
|
+
roms_output_from_restart_file.plot(var_name, time=0, xi=0, **kwargs)
|
|
245
|
+
roms_output_from_restart_file.plot(var_name, time=0, eta=0, xi=0, **kwargs)
|
|
246
|
+
roms_output_from_restart_file.plot(var_name, time=0, s=-1, eta=0, **kwargs)
|
|
247
|
+
|
|
248
|
+
kwargs = {"depth_contours": True, "layer_contours": True}
|
|
249
|
+
for var_name in ["temp", "u", "v"]:
|
|
250
|
+
roms_output_from_restart_file.plot(var_name, time=0, s=-1, **kwargs)
|
|
251
|
+
roms_output_from_restart_file.plot(var_name, time=0, eta=0, **kwargs)
|
|
252
|
+
roms_output_from_restart_file.plot(var_name, time=0, xi=0, **kwargs)
|
|
253
|
+
roms_output_from_restart_file.plot(var_name, time=0, eta=0, xi=0, **kwargs)
|
|
254
|
+
roms_output_from_restart_file.plot(var_name, time=0, s=-1, eta=0, **kwargs)
|
|
255
|
+
|
|
256
|
+
roms_output_from_restart_file.plot("zeta", time=0, **kwargs)
|
|
257
|
+
roms_output_from_restart_file.plot("zeta", time=0, eta=0, **kwargs)
|
|
258
|
+
roms_output_from_restart_file.plot("zeta", time=0, xi=0, **kwargs)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def test_plot_errors(roms_output_from_restart_file, use_dask):
|
|
262
|
+
with pytest.raises(ValueError, match="Invalid time index"):
|
|
263
|
+
roms_output_from_restart_file.plot("temp", time=10, s=-1)
|
|
264
|
+
with pytest.raises(ValueError, match="Invalid input"):
|
|
265
|
+
roms_output_from_restart_file.plot("temp", time=0)
|
|
266
|
+
with pytest.raises(ValueError, match="Ambiguous input"):
|
|
267
|
+
roms_output_from_restart_file.plot("temp", time=0, s=-1, eta=0, xi=0)
|
|
268
|
+
with pytest.raises(ValueError, match="Conflicting input"):
|
|
269
|
+
roms_output_from_restart_file.plot("zeta", time=0, eta=0, xi=0)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
import xarray as xr
|
|
4
|
+
import numpy as np
|
|
4
5
|
from roms_tools import Grid, BoundaryForcing
|
|
5
6
|
import textwrap
|
|
6
|
-
from roms_tools.
|
|
7
|
-
from conftest import
|
|
7
|
+
from roms_tools.download import download_test_data
|
|
8
|
+
from conftest import calculate_data_hash
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
import logging
|
|
10
11
|
|
|
@@ -13,19 +14,23 @@ import logging
|
|
|
13
14
|
"boundary_forcing_fixture",
|
|
14
15
|
[
|
|
15
16
|
"boundary_forcing",
|
|
16
|
-
|
|
17
|
+
"boundary_forcing_adjusted_for_zeta",
|
|
18
|
+
"boundary_forcing_with_2d_fill",
|
|
19
|
+
"boundary_forcing_with_2d_fill_adjusted_for_zeta",
|
|
17
20
|
],
|
|
18
21
|
)
|
|
19
22
|
def test_boundary_forcing_creation(boundary_forcing_fixture, request):
|
|
20
23
|
"""Test the creation of the BoundaryForcing object."""
|
|
21
24
|
|
|
22
|
-
fname = Path(download_test_data("GLORYS_coarse_test_data.nc"))
|
|
23
25
|
boundary_forcing = request.getfixturevalue(boundary_forcing_fixture)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
|
|
27
|
+
fname1 = Path(download_test_data("GLORYS_NA_20120101.nc"))
|
|
28
|
+
fname2 = Path(download_test_data("GLORYS_NA_20121231.nc"))
|
|
29
|
+
assert boundary_forcing.start_time == datetime(2012, 1, 1)
|
|
30
|
+
assert boundary_forcing.end_time == datetime(2012, 12, 31)
|
|
26
31
|
assert boundary_forcing.source == {
|
|
27
32
|
"name": "GLORYS",
|
|
28
|
-
"path":
|
|
33
|
+
"path": [fname1, fname2],
|
|
29
34
|
"climatology": False,
|
|
30
35
|
}
|
|
31
36
|
assert boundary_forcing.model_reference_date == datetime(2000, 1, 1)
|
|
@@ -44,16 +49,17 @@ def test_boundary_forcing_creation(boundary_forcing_fixture, request):
|
|
|
44
49
|
assert f"v_{direction}" in boundary_forcing.ds
|
|
45
50
|
assert f"zeta_{direction}" in boundary_forcing.ds
|
|
46
51
|
|
|
47
|
-
assert len(boundary_forcing.ds.bry_time) ==
|
|
52
|
+
assert len(boundary_forcing.ds.bry_time) == 2
|
|
48
53
|
assert boundary_forcing.ds.coords["bry_time"].attrs["units"] == "days"
|
|
49
54
|
assert not hasattr(boundary_forcing.ds, "climatology")
|
|
55
|
+
assert hasattr(boundary_forcing.ds, "adjust_depth_for_sea_surface_height")
|
|
56
|
+
assert hasattr(boundary_forcing.ds, "apply_2d_horizontal_fill")
|
|
50
57
|
|
|
51
58
|
|
|
52
59
|
@pytest.mark.parametrize(
|
|
53
60
|
"boundary_forcing_fixture",
|
|
54
61
|
[
|
|
55
62
|
"bgc_boundary_forcing_from_climatology",
|
|
56
|
-
# "bgc_boundary_forcing_from_climatology_with_2d_fill",
|
|
57
63
|
],
|
|
58
64
|
)
|
|
59
65
|
def test_boundary_forcing_creation_with_bgc(boundary_forcing_fixture, request):
|
|
@@ -155,6 +161,113 @@ def test_boundary_divided_by_land_warning(caplog, use_dask):
|
|
|
155
161
|
assert "the western boundary is divided by land" in caplog.text
|
|
156
162
|
|
|
157
163
|
|
|
164
|
+
def test_info_depth(caplog, use_dask):
|
|
165
|
+
|
|
166
|
+
grid = Grid(
|
|
167
|
+
nx=3,
|
|
168
|
+
ny=3,
|
|
169
|
+
size_x=400,
|
|
170
|
+
size_y=400,
|
|
171
|
+
center_lon=-8,
|
|
172
|
+
center_lat=58,
|
|
173
|
+
rot=0,
|
|
174
|
+
N=3, # number of vertical levels
|
|
175
|
+
theta_s=5.0, # surface control parameter
|
|
176
|
+
theta_b=2.0, # bottom control parameter
|
|
177
|
+
hc=250.0, # critical depth
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
fname1 = Path(download_test_data("GLORYS_NA_20120101.nc"))
|
|
181
|
+
fname2 = Path(download_test_data("GLORYS_NA_20121231.nc"))
|
|
182
|
+
|
|
183
|
+
with caplog.at_level(logging.INFO):
|
|
184
|
+
BoundaryForcing(
|
|
185
|
+
grid=grid,
|
|
186
|
+
start_time=datetime(2012, 1, 1),
|
|
187
|
+
end_time=datetime(2012, 12, 31),
|
|
188
|
+
source={"name": "GLORYS", "path": [fname1, fname2]},
|
|
189
|
+
adjust_depth_for_sea_surface_height=True,
|
|
190
|
+
use_dask=use_dask,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# Verify the warning message in the log
|
|
194
|
+
assert "Sea surface height will be used to adjust depth coordinates." in caplog.text
|
|
195
|
+
|
|
196
|
+
# Clear the log before the next test
|
|
197
|
+
caplog.clear()
|
|
198
|
+
|
|
199
|
+
with caplog.at_level(logging.INFO):
|
|
200
|
+
|
|
201
|
+
BoundaryForcing(
|
|
202
|
+
grid=grid,
|
|
203
|
+
start_time=datetime(2012, 1, 1),
|
|
204
|
+
end_time=datetime(2012, 12, 31),
|
|
205
|
+
source={"name": "GLORYS", "path": [fname1, fname2]},
|
|
206
|
+
adjust_depth_for_sea_surface_height=False,
|
|
207
|
+
use_dask=use_dask,
|
|
208
|
+
)
|
|
209
|
+
# Verify the warning message in the log
|
|
210
|
+
assert (
|
|
211
|
+
"Sea surface height will NOT be used to adjust depth coordinates."
|
|
212
|
+
in caplog.text
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def test_info_fill(caplog, use_dask):
|
|
217
|
+
|
|
218
|
+
grid = Grid(
|
|
219
|
+
nx=3,
|
|
220
|
+
ny=3,
|
|
221
|
+
size_x=400,
|
|
222
|
+
size_y=400,
|
|
223
|
+
center_lon=-8,
|
|
224
|
+
center_lat=58,
|
|
225
|
+
rot=0,
|
|
226
|
+
N=3, # number of vertical levels
|
|
227
|
+
theta_s=5.0, # surface control parameter
|
|
228
|
+
theta_b=2.0, # bottom control parameter
|
|
229
|
+
hc=250.0, # critical depth
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
fname1 = Path(download_test_data("GLORYS_NA_20120101.nc"))
|
|
233
|
+
fname2 = Path(download_test_data("GLORYS_NA_20121231.nc"))
|
|
234
|
+
|
|
235
|
+
with caplog.at_level(logging.INFO):
|
|
236
|
+
BoundaryForcing(
|
|
237
|
+
grid=grid,
|
|
238
|
+
start_time=datetime(2012, 1, 1),
|
|
239
|
+
end_time=datetime(2012, 12, 31),
|
|
240
|
+
source={"name": "GLORYS", "path": [fname1, fname2]},
|
|
241
|
+
apply_2d_horizontal_fill=True,
|
|
242
|
+
use_dask=use_dask,
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# Verify the warning message in the log
|
|
246
|
+
assert (
|
|
247
|
+
"Applying 2D horizontal fill to the source data before regridding."
|
|
248
|
+
in caplog.text
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
# Clear the log before the next test
|
|
252
|
+
caplog.clear()
|
|
253
|
+
|
|
254
|
+
with caplog.at_level(logging.INFO):
|
|
255
|
+
|
|
256
|
+
BoundaryForcing(
|
|
257
|
+
grid=grid,
|
|
258
|
+
start_time=datetime(2012, 1, 1),
|
|
259
|
+
end_time=datetime(2012, 12, 31),
|
|
260
|
+
source={"name": "GLORYS", "path": [fname1, fname2]},
|
|
261
|
+
apply_2d_horizontal_fill=False,
|
|
262
|
+
use_dask=use_dask,
|
|
263
|
+
)
|
|
264
|
+
# Verify the warning message in the log
|
|
265
|
+
assert (
|
|
266
|
+
"Applying 1D horizontal fill separately to each regridded boundary."
|
|
267
|
+
in caplog.text
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
|
|
158
271
|
def test_1d_and_2d_fill_coincide_if_no_land(use_dask):
|
|
159
272
|
|
|
160
273
|
# this grid lies entirely over open ocean
|
|
@@ -182,23 +295,95 @@ def test_1d_and_2d_fill_coincide_if_no_land(use_dask):
|
|
|
182
295
|
xr.testing.assert_allclose(bf_1d_fill.ds, bf_2d_fill.ds, rtol=1.0e-4)
|
|
183
296
|
|
|
184
297
|
|
|
185
|
-
|
|
298
|
+
@pytest.mark.parametrize(
|
|
299
|
+
"boundary_forcing_fixture",
|
|
300
|
+
[
|
|
301
|
+
"boundary_forcing_adjusted_for_zeta",
|
|
302
|
+
"boundary_forcing_with_2d_fill_adjusted_for_zeta",
|
|
303
|
+
],
|
|
304
|
+
)
|
|
305
|
+
def test_correct_depth_coords_adjusted_for_zeta(
|
|
306
|
+
boundary_forcing_fixture, request, use_dask
|
|
307
|
+
):
|
|
308
|
+
|
|
309
|
+
boundary_forcing = request.getfixturevalue(boundary_forcing_fixture)
|
|
310
|
+
|
|
311
|
+
for direction in ["south", "east", "north", "west"]:
|
|
312
|
+
|
|
313
|
+
# Test that uppermost interface coincides with sea surface height
|
|
314
|
+
assert np.allclose(
|
|
315
|
+
boundary_forcing.ds_depth_coords[f"interface_depth_rho_{direction}"]
|
|
316
|
+
.isel(s_w=-1)
|
|
317
|
+
.values,
|
|
318
|
+
-boundary_forcing.ds[f"zeta_{direction}"].values,
|
|
319
|
+
atol=1e-6,
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
@pytest.mark.parametrize(
|
|
324
|
+
"boundary_forcing_fixture",
|
|
325
|
+
[
|
|
326
|
+
"boundary_forcing",
|
|
327
|
+
"boundary_forcing_with_2d_fill",
|
|
328
|
+
],
|
|
329
|
+
)
|
|
330
|
+
def test_correct_depth_coords_zero_zeta(boundary_forcing_fixture, request, use_dask):
|
|
331
|
+
|
|
332
|
+
boundary_forcing = request.getfixturevalue(boundary_forcing_fixture)
|
|
333
|
+
|
|
334
|
+
for direction in ["south", "east", "north", "west"]:
|
|
335
|
+
|
|
336
|
+
# Test that uppermost interface coincides with sea surface height
|
|
337
|
+
assert np.allclose(
|
|
338
|
+
boundary_forcing.ds_depth_coords[f"interface_depth_rho_{direction}"]
|
|
339
|
+
.isel(s_w=-1)
|
|
340
|
+
.values,
|
|
341
|
+
0 * boundary_forcing.ds[f"zeta_{direction}"].values,
|
|
342
|
+
atol=1e-6,
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
@pytest.mark.parametrize(
|
|
347
|
+
"boundary_forcing_fixture",
|
|
348
|
+
[
|
|
349
|
+
"boundary_forcing",
|
|
350
|
+
"boundary_forcing_with_2d_fill",
|
|
351
|
+
"boundary_forcing_adjusted_for_zeta",
|
|
352
|
+
"boundary_forcing_with_2d_fill_adjusted_for_zeta",
|
|
353
|
+
],
|
|
354
|
+
)
|
|
355
|
+
def test_boundary_forcing_plot(boundary_forcing_fixture, request):
|
|
186
356
|
"""Test plot."""
|
|
357
|
+
boundary_forcing = request.getfixturevalue(boundary_forcing_fixture)
|
|
187
358
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
359
|
+
for direction in ["south", "east", "north", "west"]:
|
|
360
|
+
for layer_contours in [False, True]:
|
|
361
|
+
boundary_forcing.plot(
|
|
362
|
+
var_name=f"temp_{direction}", layer_contours=layer_contours
|
|
363
|
+
)
|
|
364
|
+
boundary_forcing.plot(
|
|
365
|
+
var_name=f"u_{direction}", layer_contours=layer_contours
|
|
366
|
+
)
|
|
367
|
+
boundary_forcing.plot(
|
|
368
|
+
var_name=f"v_{direction}", layer_contours=layer_contours
|
|
369
|
+
)
|
|
370
|
+
boundary_forcing.plot(var_name=f"zeta_{direction}")
|
|
371
|
+
boundary_forcing.plot(var_name=f"vbar_{direction}")
|
|
372
|
+
boundary_forcing.plot(var_name=f"ubar_{direction}")
|
|
198
373
|
|
|
199
374
|
|
|
200
|
-
|
|
375
|
+
@pytest.mark.parametrize(
|
|
376
|
+
"boundary_forcing_fixture",
|
|
377
|
+
[
|
|
378
|
+
"boundary_forcing",
|
|
379
|
+
"boundary_forcing_with_2d_fill",
|
|
380
|
+
"boundary_forcing_adjusted_for_zeta",
|
|
381
|
+
"boundary_forcing_with_2d_fill_adjusted_for_zeta",
|
|
382
|
+
],
|
|
383
|
+
)
|
|
384
|
+
def test_boundary_forcing_save(boundary_forcing_fixture, request, tmp_path):
|
|
201
385
|
"""Test save method."""
|
|
386
|
+
boundary_forcing = request.getfixturevalue(boundary_forcing_fixture)
|
|
202
387
|
|
|
203
388
|
for file_str in ["test_bf", "test_bf.nc"]:
|
|
204
389
|
# Create a temporary filepath using the tmp_path fixture
|
|
@@ -207,8 +392,8 @@ def test_boundary_forcing_save(boundary_forcing, tmp_path):
|
|
|
207
392
|
str(tmp_path / file_str),
|
|
208
393
|
]: # test for Path object and str
|
|
209
394
|
|
|
210
|
-
# Test saving without
|
|
211
|
-
saved_filenames = boundary_forcing.save(filepath)
|
|
395
|
+
# Test saving without grouping
|
|
396
|
+
saved_filenames = boundary_forcing.save(filepath, group=False)
|
|
212
397
|
|
|
213
398
|
filepath_str = str(Path(filepath).with_suffix(""))
|
|
214
399
|
expected_filepath = Path(f"{filepath_str}.nc")
|
|
@@ -217,28 +402,16 @@ def test_boundary_forcing_save(boundary_forcing, tmp_path):
|
|
|
217
402
|
assert expected_filepath.exists()
|
|
218
403
|
expected_filepath.unlink()
|
|
219
404
|
|
|
220
|
-
# Test saving
|
|
405
|
+
# Test saving with grouping
|
|
221
406
|
saved_filenames = boundary_forcing.save(filepath, group=True)
|
|
222
407
|
|
|
223
408
|
filepath_str = str(Path(filepath).with_suffix(""))
|
|
224
|
-
expected_filepath = Path(f"{filepath_str}
|
|
409
|
+
expected_filepath = Path(f"{filepath_str}_2012.nc")
|
|
225
410
|
|
|
226
411
|
assert saved_filenames == [expected_filepath]
|
|
227
412
|
assert expected_filepath.exists()
|
|
228
413
|
expected_filepath.unlink()
|
|
229
414
|
|
|
230
|
-
# Test saving with partitioning and grouping
|
|
231
|
-
saved_filenames = boundary_forcing.save(filepath, np_eta=2, group=True)
|
|
232
|
-
expected_filepath_list = [
|
|
233
|
-
Path(filepath_str + f"_202106.{index}.nc") for index in range(2)
|
|
234
|
-
]
|
|
235
|
-
|
|
236
|
-
assert saved_filenames == expected_filepath_list
|
|
237
|
-
|
|
238
|
-
for expected_filepath in expected_filepath_list:
|
|
239
|
-
assert expected_filepath.exists()
|
|
240
|
-
expected_filepath.unlink()
|
|
241
|
-
|
|
242
415
|
|
|
243
416
|
def test_bgc_boundary_forcing_plot(bgc_boundary_forcing_from_climatology):
|
|
244
417
|
"""Test plot method."""
|
|
@@ -264,7 +437,9 @@ def test_bgc_boundary_forcing_save(bgc_boundary_forcing_from_climatology, tmp_pa
|
|
|
264
437
|
]: # test for Path object and str
|
|
265
438
|
|
|
266
439
|
# Test saving without partitioning and grouping
|
|
267
|
-
saved_filenames = bgc_boundary_forcing_from_climatology.save(
|
|
440
|
+
saved_filenames = bgc_boundary_forcing_from_climatology.save(
|
|
441
|
+
filepath, group=False
|
|
442
|
+
)
|
|
268
443
|
|
|
269
444
|
filepath_str = str(Path(filepath).with_suffix(""))
|
|
270
445
|
expected_filepath = Path(f"{filepath_str}.nc")
|
|
@@ -283,20 +458,6 @@ def test_bgc_boundary_forcing_save(bgc_boundary_forcing_from_climatology, tmp_pa
|
|
|
283
458
|
assert expected_filepath.exists()
|
|
284
459
|
expected_filepath.unlink()
|
|
285
460
|
|
|
286
|
-
# Test saving with partitioning
|
|
287
|
-
saved_filenames = bgc_boundary_forcing_from_climatology.save(
|
|
288
|
-
filepath, np_xi=2, group=True
|
|
289
|
-
)
|
|
290
|
-
|
|
291
|
-
expected_filepath_list = [
|
|
292
|
-
Path(filepath_str + f"_clim.{index}.nc") for index in range(2)
|
|
293
|
-
]
|
|
294
|
-
assert saved_filenames == expected_filepath_list
|
|
295
|
-
|
|
296
|
-
for expected_filepath in expected_filepath_list:
|
|
297
|
-
assert expected_filepath.exists()
|
|
298
|
-
expected_filepath.unlink()
|
|
299
|
-
|
|
300
461
|
|
|
301
462
|
@pytest.mark.parametrize(
|
|
302
463
|
"bdry_forcing_fixture",
|
|
@@ -341,11 +502,12 @@ def test_files_have_same_hash(boundary_forcing, tmp_path, use_dask):
|
|
|
341
502
|
|
|
342
503
|
filepath_str1 = str(Path(filepath1).with_suffix(""))
|
|
343
504
|
filepath_str2 = str(Path(filepath2).with_suffix(""))
|
|
344
|
-
expected_filepath1 = f"{filepath_str1}
|
|
345
|
-
expected_filepath2 = f"{filepath_str2}
|
|
505
|
+
expected_filepath1 = f"{filepath_str1}_2012.nc"
|
|
506
|
+
expected_filepath2 = f"{filepath_str2}_2012.nc"
|
|
346
507
|
|
|
347
|
-
|
|
348
|
-
|
|
508
|
+
# Only compare hash of datasets because metadata is non-deterministic with dask
|
|
509
|
+
hash1 = calculate_data_hash(expected_filepath1)
|
|
510
|
+
hash2 = calculate_data_hash(expected_filepath2)
|
|
349
511
|
|
|
350
512
|
assert hash1 == hash2, f"Hashes do not match: {hash1} != {hash2}"
|
|
351
513
|
|
|
@@ -372,8 +534,9 @@ def test_files_have_same_hash_clim(
|
|
|
372
534
|
expected_filepath1 = f"{filepath_str1}_clim.nc"
|
|
373
535
|
expected_filepath2 = f"{filepath_str2}_clim.nc"
|
|
374
536
|
|
|
375
|
-
|
|
376
|
-
|
|
537
|
+
# Only compare hash of datasets because metadata is non-deterministic with dask
|
|
538
|
+
hash1 = calculate_data_hash(expected_filepath1)
|
|
539
|
+
hash2 = calculate_data_hash(expected_filepath2)
|
|
377
540
|
|
|
378
541
|
assert hash1 == hash2, f"Hashes do not match: {hash1} != {hash2}"
|
|
379
542
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"adjust_depth_for_sea_surface_height": "False",
|
|
3
|
+
"apply_2d_horizontal_fill": "False",
|
|
4
|
+
"end_time": "2012-12-31 00:00:00",
|
|
3
5
|
"hc": 250.0,
|
|
4
6
|
"model_reference_date": "2000-01-01 00:00:00",
|
|
5
|
-
"roms_tools_version": "0.1.
|
|
7
|
+
"roms_tools_version": "0.1.dev177",
|
|
6
8
|
"source": "GLORYS",
|
|
7
|
-
"start_time": "
|
|
9
|
+
"start_time": "2012-01-01 00:00:00",
|
|
8
10
|
"theta_b": 2.0,
|
|
9
11
|
"theta_s": 5.0,
|
|
10
12
|
"title": "ROMS boundary forcing file created by ROMS-Tools"
|