roms-tools 3.3.0__py3-none-any.whl → 3.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.
Files changed (174) hide show
  1. roms_tools/__init__.py +1 -1
  2. roms_tools/analysis/cdr_ensemble.py +10 -13
  3. roms_tools/analysis/roms_output.py +5 -304
  4. roms_tools/{download.py → datasets/download.py} +1 -0
  5. roms_tools/{setup → datasets}/lat_lon_datasets.py +76 -64
  6. roms_tools/{setup → datasets}/river_datasets.py +9 -4
  7. roms_tools/datasets/roms_dataset.py +767 -0
  8. roms_tools/datasets/utils.py +475 -0
  9. roms_tools/{setup/fill.py → fill.py} +110 -13
  10. roms_tools/plot.py +4 -4
  11. roms_tools/setup/boundary_forcing.py +51 -43
  12. roms_tools/setup/cdr_release.py +2 -4
  13. roms_tools/setup/grid.py +29 -12
  14. roms_tools/setup/initial_conditions.py +19 -19
  15. roms_tools/setup/nesting.py +8 -4
  16. roms_tools/setup/river_forcing.py +4 -4
  17. roms_tools/setup/surface_forcing.py +14 -9
  18. roms_tools/setup/tides.py +1 -1
  19. roms_tools/setup/topography.py +10 -2
  20. roms_tools/setup/utils.py +72 -524
  21. roms_tools/tests/test_analysis/test_cdr_ensemble.py +4 -6
  22. roms_tools/tests/test_analysis/test_roms_output.py +1 -220
  23. roms_tools/tests/{test_setup → test_datasets}/test_lat_lon_datasets.py +4 -4
  24. roms_tools/tests/{test_setup → test_datasets}/test_river_datasets.py +1 -1
  25. roms_tools/tests/test_datasets/test_roms_dataset.py +539 -0
  26. roms_tools/tests/test_datasets/test_utils.py +527 -0
  27. roms_tools/tests/{test_setup/test_fill.py → test_fill.py} +72 -9
  28. roms_tools/tests/test_setup/test_boundary_forcing.py +57 -138
  29. roms_tools/tests/test_setup/test_cdr_release.py +4 -5
  30. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zarr.json +293 -2021
  31. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zarr.json +294 -2022
  32. roms_tools/tests/test_setup/test_grid.py +42 -1
  33. roms_tools/tests/test_setup/test_initial_conditions.py +3 -94
  34. roms_tools/tests/test_setup/test_nesting.py +2 -1
  35. roms_tools/tests/test_setup/test_surface_forcing.py +1 -1
  36. roms_tools/tests/test_setup/test_tides.py +1 -1
  37. roms_tools/tests/test_setup/test_utils.py +100 -15
  38. roms_tools/tests/test_tiling/test_partition.py +63 -15
  39. roms_tools/tests/test_utils.py +78 -0
  40. roms_tools/tiling/partition.py +81 -211
  41. roms_tools/utils.py +193 -0
  42. {roms_tools-3.3.0.dist-info → roms_tools-3.4.0.dist-info}/METADATA +1 -1
  43. {roms_tools-3.3.0.dist-info → roms_tools-3.4.0.dist-info}/RECORD +46 -170
  44. {roms_tools-3.3.0.dist-info → roms_tools-3.4.0.dist-info}/WHEEL +1 -1
  45. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/c/0/0/0 +0 -0
  46. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/zarr.json +0 -54
  47. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/c/0/0/0 +0 -0
  48. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/zarr.json +0 -54
  49. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/c/0/0/0 +0 -0
  50. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/zarr.json +0 -54
  51. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/c/0/0/0 +0 -0
  52. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/zarr.json +0 -54
  53. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/c/0/0/0 +0 -0
  54. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/zarr.json +0 -54
  55. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/c/0/0/0 +0 -0
  56. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/zarr.json +0 -54
  57. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/c/0/0/0 +0 -0
  58. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/zarr.json +0 -54
  59. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/c/0/0/0 +0 -0
  60. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/zarr.json +0 -54
  61. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/c/0/0/0 +0 -0
  62. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/zarr.json +0 -54
  63. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/c/0/0/0 +0 -0
  64. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/zarr.json +0 -54
  65. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/c/0/0/0 +0 -0
  66. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/zarr.json +0 -54
  67. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/c/0/0/0 +0 -0
  68. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/zarr.json +0 -54
  69. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/c/0/0/0 +0 -0
  70. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/zarr.json +0 -54
  71. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/c/0/0/0 +0 -0
  72. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/zarr.json +0 -54
  73. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/c/0/0/0 +0 -0
  74. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/zarr.json +0 -54
  75. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/c/0/0/0 +0 -0
  76. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/zarr.json +0 -54
  77. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/c/0/0/0 +0 -0
  78. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/zarr.json +0 -54
  79. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/c/0/0/0 +0 -0
  80. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/zarr.json +0 -54
  81. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/c/0/0/0 +0 -0
  82. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/zarr.json +0 -54
  83. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/c/0/0/0 +0 -0
  84. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/zarr.json +0 -54
  85. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/c/0/0/0 +0 -0
  86. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/zarr.json +0 -54
  87. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/c/0/0/0 +0 -0
  88. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/zarr.json +0 -54
  89. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/c/0/0/0 +0 -0
  90. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/zarr.json +0 -54
  91. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/c/0/0/0 +0 -0
  92. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/zarr.json +0 -54
  93. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/c/0/0/0 +0 -0
  94. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/zarr.json +0 -54
  95. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/c/0/0/0 +0 -0
  96. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/zarr.json +0 -54
  97. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/c/0/0/0 +0 -0
  98. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/zarr.json +0 -54
  99. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/c/0/0/0 +0 -0
  100. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/zarr.json +0 -54
  101. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/c/0/0/0 +0 -0
  102. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/zarr.json +0 -54
  103. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/c/0/0/0 +0 -0
  104. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/zarr.json +0 -54
  105. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/c/0/0/0 +0 -0
  106. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/zarr.json +0 -54
  107. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/c/0/0/0 +0 -0
  108. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/zarr.json +0 -54
  109. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_west/c/0/0/0 +0 -0
  110. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_west/zarr.json +0 -54
  111. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_west/c/0/0/0 +0 -0
  112. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_west/zarr.json +0 -54
  113. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_west/c/0/0/0 +0 -0
  114. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_west/zarr.json +0 -54
  115. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_west/c/0/0/0 +0 -0
  116. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_west/zarr.json +0 -54
  117. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_west/c/0/0/0 +0 -0
  118. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_west/zarr.json +0 -54
  119. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_west/c/0/0/0 +0 -0
  120. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_west/zarr.json +0 -54
  121. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_west/c/0/0/0 +0 -0
  122. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_west/zarr.json +0 -54
  123. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_west/c/0/0/0 +0 -0
  124. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_west/zarr.json +0 -54
  125. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_west/c/0/0/0 +0 -0
  126. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_west/zarr.json +0 -54
  127. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_west/c/0/0/0 +0 -0
  128. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_west/zarr.json +0 -54
  129. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_west/c/0/0/0 +0 -0
  130. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_west/zarr.json +0 -54
  131. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_west/c/0/0/0 +0 -0
  132. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_west/zarr.json +0 -54
  133. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_west/c/0/0/0 +0 -0
  134. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_west/zarr.json +0 -54
  135. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_west/c/0/0/0 +0 -0
  136. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_west/zarr.json +0 -54
  137. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_west/c/0/0/0 +0 -0
  138. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_west/zarr.json +0 -54
  139. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_west/c/0/0/0 +0 -0
  140. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_west/zarr.json +0 -54
  141. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_west/c/0/0/0 +0 -0
  142. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_west/zarr.json +0 -54
  143. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_west/c/0/0/0 +0 -0
  144. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_west/zarr.json +0 -54
  145. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_west/c/0/0/0 +0 -0
  146. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_west/zarr.json +0 -54
  147. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_west/c/0/0/0 +0 -0
  148. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_west/zarr.json +0 -54
  149. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_west/c/0/0/0 +0 -0
  150. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_west/zarr.json +0 -54
  151. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_west/c/0/0/0 +0 -0
  152. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_west/zarr.json +0 -54
  153. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_west/c/0/0/0 +0 -0
  154. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_west/zarr.json +0 -54
  155. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_west/c/0/0/0 +0 -0
  156. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_west/zarr.json +0 -54
  157. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_west/c/0/0/0 +0 -0
  158. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_west/zarr.json +0 -54
  159. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_west/c/0/0/0 +0 -0
  160. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_west/zarr.json +0 -54
  161. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_west/c/0/0/0 +0 -0
  162. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_west/zarr.json +0 -54
  163. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_west/c/0/0/0 +0 -0
  164. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_west/zarr.json +0 -54
  165. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_west/c/0/0/0 +0 -0
  166. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_west/zarr.json +0 -54
  167. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_west/c/0/0/0 +0 -0
  168. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_west/zarr.json +0 -54
  169. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_west/c/0/0/0 +0 -0
  170. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_west/zarr.json +0 -54
  171. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_west/c/0/0/0 +0 -0
  172. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_west/zarr.json +0 -54
  173. {roms_tools-3.3.0.dist-info → roms_tools-3.4.0.dist-info}/licenses/LICENSE +0 -0
  174. {roms_tools-3.3.0.dist-info → roms_tools-3.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,539 @@
1
+ import logging
2
+ import os
3
+ from datetime import datetime
4
+ from pathlib import Path
5
+
6
+ import numpy as np
7
+ import pytest
8
+ import xarray as xr
9
+
10
+ from roms_tools import Grid
11
+ from roms_tools.datasets.download import download_test_data
12
+ from roms_tools.datasets.roms_dataset import ROMSDataset, choose_subdomain
13
+ from roms_tools.setup.utils import get_target_coords
14
+
15
+ try:
16
+ import xesmf # type: ignore
17
+ except ImportError:
18
+ xesmf = None
19
+
20
+
21
+ @pytest.fixture
22
+ def roms_dataset_from_restart_file(use_dask):
23
+ fname_grid = Path(download_test_data("epac25km_grd.nc"))
24
+ grid = Grid.from_file(fname_grid)
25
+
26
+ # Single file
27
+ return ROMSDataset(
28
+ grid=grid,
29
+ path=Path(download_test_data("eastpac25km_rst.19980106000000.nc")),
30
+ use_dask=use_dask,
31
+ )
32
+
33
+
34
+ @pytest.fixture
35
+ def roms_dataset_from_restart_file_adjusted_for_zeta(use_dask):
36
+ fname_grid = Path(download_test_data("epac25km_grd.nc"))
37
+ grid = Grid.from_file(fname_grid)
38
+
39
+ # Single file
40
+ return ROMSDataset(
41
+ grid=grid,
42
+ path=Path(download_test_data("eastpac25km_rst.19980106000000.nc")),
43
+ adjust_depth_for_sea_surface_height=True,
44
+ use_dask=use_dask,
45
+ )
46
+
47
+
48
+ @pytest.fixture
49
+ def roms_dataset_from_restart_file_with_straddling_grid(use_dask):
50
+ # Make fake grid that straddles the dateline and that has consistent sizes with test data below
51
+ grid = Grid(
52
+ nx=8, ny=13, center_lon=0, center_lat=60, rot=32, size_x=244, size_y=365
53
+ )
54
+
55
+ return ROMSDataset(
56
+ grid=grid,
57
+ path=Path(download_test_data("eastpac25km_rst.19980106000000.nc")),
58
+ use_dask=use_dask,
59
+ )
60
+
61
+
62
+ @pytest.mark.parametrize(
63
+ "roms_dataset_fixture",
64
+ [
65
+ "roms_dataset_from_restart_file",
66
+ "roms_dataset_from_restart_file_adjusted_for_zeta",
67
+ "roms_dataset_from_restart_file_with_straddling_grid",
68
+ ],
69
+ )
70
+ def test_load_model_output_file(roms_dataset_fixture, request):
71
+ roms_dataset = request.getfixturevalue(roms_dataset_fixture)
72
+
73
+ assert isinstance(roms_dataset.ds, xr.Dataset)
74
+
75
+
76
+ @pytest.fixture
77
+ def roms_dataset_from_two_restart_files(use_dask):
78
+ fname_grid = Path(download_test_data("epac25km_grd.nc"))
79
+ grid = Grid.from_file(fname_grid)
80
+
81
+ # List of files
82
+ file1 = Path(download_test_data("eastpac25km_rst.19980106000000.nc"))
83
+ file2 = Path(download_test_data("eastpac25km_rst.19980126000000.nc"))
84
+ return ROMSDataset(grid=grid, path=[file1, file2], use_dask=use_dask)
85
+
86
+
87
+ def test_load_model_output_file_list(roms_dataset_from_two_restart_files):
88
+ assert isinstance(roms_dataset_from_two_restart_files.ds, xr.Dataset)
89
+
90
+
91
+ def test_load_model_output_with_wildcard(use_dask):
92
+ fname_grid = Path(download_test_data("epac25km_grd.nc"))
93
+ grid = Grid.from_file(fname_grid)
94
+
95
+ # Download at least two files, so these will be found within the pooch directory
96
+ Path(download_test_data("eastpac25km_rst.19980106000000.nc"))
97
+ Path(download_test_data("eastpac25km_rst.19980126000000.nc"))
98
+ directory = Path(
99
+ os.path.dirname(download_test_data("eastpac25km_rst.19980106000000.nc"))
100
+ )
101
+
102
+ output = ROMSDataset(grid=grid, path=directory / "*rst*.nc", use_dask=use_dask)
103
+ assert isinstance(output.ds, xr.Dataset)
104
+
105
+
106
+ def test_invalid_path(use_dask):
107
+ fname_grid = Path(download_test_data("epac25km_grd.nc"))
108
+ grid = Grid.from_file(fname_grid)
109
+
110
+ # Non-existent file
111
+ with pytest.raises(FileNotFoundError):
112
+ ROMSDataset(
113
+ grid=grid,
114
+ path=Path("/path/to/nonexistent/file.nc"),
115
+ use_dask=use_dask,
116
+ )
117
+
118
+
119
+ def test_check_consistency_data_grid(use_dask):
120
+ grid_params = {
121
+ "nx": 5,
122
+ "ny": 5,
123
+ "center_lon": -128,
124
+ "center_lat": 9,
125
+ "size_x": 100,
126
+ "size_y": 100,
127
+ }
128
+ grid = Grid(**grid_params)
129
+
130
+ with pytest.raises(ValueError, match="Inconsistent dataset dimensions"):
131
+ ROMSDataset(
132
+ grid=grid,
133
+ path=Path(download_test_data("eastpac25km_rst.19980106000000.nc")),
134
+ use_dask=use_dask,
135
+ )
136
+
137
+
138
+ def test_set_correct_model_reference_date(use_dask):
139
+ fname_grid = Path(download_test_data("epac25km_grd.nc"))
140
+ grid = Grid.from_file(fname_grid)
141
+
142
+ output = ROMSDataset(
143
+ grid=grid,
144
+ path=Path(download_test_data("eastpac25km_rst.19980106000000.nc")),
145
+ use_dask=use_dask,
146
+ )
147
+ assert output.model_reference_date == datetime(1995, 1, 1)
148
+
149
+
150
+ def test_model_reference_date_mismatch(use_dask):
151
+ fname_grid = Path(download_test_data("epac25km_grd.nc"))
152
+ grid = Grid.from_file(fname_grid)
153
+
154
+ # Create a ROMSDataset with a specified model_reference_date
155
+ model_ref_date = datetime(2020, 1, 1)
156
+ with pytest.raises(
157
+ ValueError, match="Mismatch between `self.model_reference_date`"
158
+ ):
159
+ ROMSDataset(
160
+ grid=grid,
161
+ path=Path(download_test_data("eastpac25km_rst.19980106000000.nc")),
162
+ model_reference_date=model_ref_date,
163
+ use_dask=use_dask,
164
+ )
165
+
166
+
167
+ def test_model_reference_date_no_metadata(use_dask, tmp_path, caplog):
168
+ # Helper function to handle the test logic for cases where metadata is missing or invalid
169
+ def test_no_metadata(faulty_ocean_time_attr, expected_exception, log_message=None):
170
+ ds = xr.open_dataset(fname)
171
+ ds["ocean_time"].attrs = faulty_ocean_time_attr
172
+
173
+ # Write modified dataset to a new file
174
+ fname_mod = tmp_path / "eastpac25km_rst.19980106000000_without_metadata.nc"
175
+ ds.to_netcdf(fname_mod)
176
+
177
+ # Test case 1: Expecting a ValueError when metadata is missing or invalid
178
+ with pytest.raises(
179
+ expected_exception,
180
+ match="Model reference date could not be inferred from the metadata",
181
+ ):
182
+ ROMSDataset(grid=grid, path=fname_mod, use_dask=use_dask)
183
+
184
+ # Test case 2: When a model reference date is explicitly set, verify the warning
185
+ with caplog.at_level(logging.WARNING):
186
+ ROMSDataset(
187
+ grid=grid,
188
+ path=fname_mod,
189
+ model_reference_date=datetime(1995, 1, 1),
190
+ use_dask=use_dask,
191
+ )
192
+
193
+ if log_message:
194
+ # Verify the warning message in the log
195
+ assert log_message in caplog.text
196
+
197
+ fname_mod.unlink()
198
+
199
+ # Load grid and test data
200
+ fname_grid = Path(download_test_data("epac25km_grd.nc"))
201
+ grid = Grid.from_file(fname_grid)
202
+ fname = download_test_data("eastpac25km_rst.19980106000000.nc")
203
+
204
+ # Test 1: Ocean time attribute 'long_name' is missing
205
+ test_no_metadata({}, ValueError)
206
+
207
+ # Test 2: Ocean time attribute 'long_name' contains invalid information
208
+ test_no_metadata(
209
+ {"long_name": "some random text"},
210
+ ValueError,
211
+ "Could not infer the model reference date from the metadata.",
212
+ )
213
+
214
+
215
+ def test_compute_depth_coordinates(use_dask):
216
+ fname_grid = Path(download_test_data("epac25km_grd.nc"))
217
+ grid = Grid.from_file(fname_grid)
218
+ fname_restart1 = Path(download_test_data("eastpac25km_rst.19980106000000.nc"))
219
+
220
+ for adjust_depth_for_sea_surface_height in [True, False]:
221
+ output = ROMSDataset(
222
+ grid=grid,
223
+ path=fname_restart1,
224
+ use_dask=use_dask,
225
+ adjust_depth_for_sea_surface_height=adjust_depth_for_sea_surface_height,
226
+ )
227
+
228
+ # Before calling get_vertical_coordinates, check if the dataset doesn't already have depth coordinates
229
+ assert "layer_depth_rho" not in output.ds_depth_coords.data_vars
230
+
231
+ # Call the method to get vertical coordinates
232
+ output._get_depth_coordinates(depth_type="layer")
233
+
234
+ # Check if the depth coordinates were added
235
+ assert "layer_depth_rho" in output.ds_depth_coords.data_vars
236
+
237
+
238
+ def test_missing_zeta_gets_raised(use_dask):
239
+ """Test that a ValueError is raised when `zeta` is missing from the dataset and
240
+ `adjust_depth_for_sea_surface_height` is enabled.
241
+ """
242
+ # Load the grid
243
+ fname_grid = Path(download_test_data("epac25km_grd.nc"))
244
+ grid = Grid.from_file(fname_grid)
245
+
246
+ # Load the ROMS output
247
+ fname_restart1 = Path(download_test_data("eastpac25km_rst.19980106000000.nc"))
248
+ roms_output = ROMSDataset(
249
+ grid=grid,
250
+ path=fname_restart1,
251
+ use_dask=use_dask,
252
+ adjust_depth_for_sea_surface_height=True,
253
+ )
254
+
255
+ # Remove `zeta` from the dataset
256
+ object.__setattr__(
257
+ roms_output, "ds", roms_output.ds.drop_vars("zeta", errors="ignore")
258
+ )
259
+
260
+ # Expect ValueError when calling `_get_depth_coordinates`
261
+ with pytest.raises(
262
+ ValueError,
263
+ match="`zeta` is required in provided ROMS output when `adjust_depth_for_sea_surface_height` is enabled.",
264
+ ):
265
+ roms_output._get_depth_coordinates()
266
+
267
+
268
+ def test_check_vertical_coordinate_mismatch(use_dask):
269
+ fname_grid = Path(download_test_data("epac25km_grd.nc"))
270
+ grid = Grid.from_file(fname_grid)
271
+
272
+ fname_restart1 = Path(download_test_data("eastpac25km_rst.19980106000000.nc"))
273
+ output = ROMSDataset(grid=grid, path=fname_restart1, use_dask=use_dask)
274
+
275
+ # create a mock dataset with inconsistent vertical coordinate parameters
276
+ ds_mock = output.ds.copy()
277
+
278
+ # Modify one of the vertical coordinate attributes to cause a mismatch
279
+ ds_mock.attrs["theta_s"] = 999
280
+
281
+ # Check if ValueError is raised due to mismatch
282
+ with pytest.raises(ValueError, match="theta_s from grid"):
283
+ output._check_vertical_coordinate(ds_mock)
284
+
285
+ # create a mock dataset with inconsistent vertical coordinate parameters
286
+ ds_mock = output.ds.copy()
287
+
288
+ # Modify one of the vertical coordinate attributes to cause a mismatch
289
+ ds_mock.attrs["Cs_w"] = ds_mock.attrs["Cs_w"] + 0.01
290
+
291
+ # Check if ValueError is raised due to mismatch
292
+ with pytest.raises(ValueError, match="Cs_w from grid"):
293
+ output._check_vertical_coordinate(ds_mock)
294
+
295
+
296
+ def test_that_coordinates_and_masks_are_added(use_dask):
297
+ fname_grid = Path(download_test_data("epac25km_grd.nc"))
298
+ grid = Grid.from_file(fname_grid)
299
+
300
+ fname_restart1 = Path(download_test_data("eastpac25km_rst.19980106000000.nc"))
301
+ output = ROMSDataset(grid=grid, path=fname_restart1, use_dask=use_dask)
302
+
303
+ assert "time" in output.ds.coords
304
+ assert "lat_rho" in output.ds.coords
305
+ assert "lon_rho" in output.ds.coords
306
+ assert "mask_rho" in output.ds
307
+ assert "mask_u" in output.ds
308
+ assert "mask_v" in output.ds
309
+
310
+
311
+ def test_apply_lateral_fill():
312
+ grid_parameters = {
313
+ "nx": 10,
314
+ "ny": 10,
315
+ "size_x": 2500,
316
+ "size_y": 3000,
317
+ "center_lon": -30,
318
+ "center_lat": 57,
319
+ "rot": -20,
320
+ }
321
+
322
+ grid = Grid(**grid_parameters)
323
+
324
+ ds = xr.Dataset()
325
+ ds["field"] = 5 * grid.ds.mask_rho.copy()
326
+ ds["mask_rho"] = grid.ds.mask_rho.copy()
327
+ ds["mask_u"] = grid.ds.mask_u.copy()
328
+ ds["mask_v"] = grid.ds.mask_v.copy()
329
+
330
+ roms_dataset = ROMSDataset.__new__(ROMSDataset)
331
+ roms_dataset.ds = ds
332
+ roms_dataset.grid = grid
333
+
334
+ # Check that initially some values are zero (land)
335
+ assert (roms_dataset.ds["field"].values == 0).any()
336
+
337
+ roms_dataset.apply_lateral_fill()
338
+
339
+ # After filling the ocean values (all 5) should have propagated into land
340
+ assert (roms_dataset.ds["field"].values == 5).all()
341
+
342
+
343
+ # Test choose_subdomain
344
+ grid_cases = [
345
+ # --- SMALL INSIDE WESTERN HEMISPHERE -----------------------------------
346
+ (
347
+ # big grid west, does NOT cross Greenwich
348
+ {
349
+ "nx": 40,
350
+ "ny": 40,
351
+ "size_x": 4000,
352
+ "size_y": 4000,
353
+ "center_lon": -30,
354
+ "center_lat": 50,
355
+ "rot": 0,
356
+ },
357
+ # small grid fully west
358
+ {
359
+ "nx": 10,
360
+ "ny": 10,
361
+ "size_x": 500,
362
+ "size_y": 500,
363
+ "center_lon": -20,
364
+ "center_lat": 50,
365
+ "rot": 0,
366
+ },
367
+ ),
368
+ # --- SMALL INSIDE EASTERN HEMISPHERE ----------------------------------
369
+ (
370
+ {
371
+ "nx": 40,
372
+ "ny": 40,
373
+ "size_x": 4000,
374
+ "size_y": 4000,
375
+ "center_lon": 10,
376
+ "center_lat": 45,
377
+ "rot": 0,
378
+ },
379
+ {
380
+ "nx": 10,
381
+ "ny": 10,
382
+ "size_x": 500,
383
+ "size_y": 500,
384
+ "center_lon": 20,
385
+ "center_lat": 45,
386
+ "rot": 0,
387
+ },
388
+ ),
389
+ # --- SMALL GRID STRADDLING GREENWICH ----------------------------------
390
+ (
391
+ # big grid centered slightly west
392
+ {
393
+ "nx": 40,
394
+ "ny": 40,
395
+ "size_x": 5000,
396
+ "size_y": 4000,
397
+ "center_lon": -5,
398
+ "center_lat": 45,
399
+ "rot": 0,
400
+ },
401
+ # small grid crosses 0°
402
+ {
403
+ "nx": 10,
404
+ "ny": 10,
405
+ "size_x": 600,
406
+ "size_y": 600,
407
+ "center_lon": 0,
408
+ "center_lat": 45,
409
+ "rot": 0,
410
+ },
411
+ ),
412
+ # --- LARGE GRID CROSSES GREENWICH, SMALL IS WEST -----------------------
413
+ (
414
+ {
415
+ "nx": 50,
416
+ "ny": 50,
417
+ "size_x": 8000,
418
+ "size_y": 5000,
419
+ "center_lon": -2,
420
+ "center_lat": 40,
421
+ "rot": 0,
422
+ },
423
+ {
424
+ "nx": 10,
425
+ "ny": 10,
426
+ "size_x": 400,
427
+ "size_y": 400,
428
+ "center_lon": -10,
429
+ "center_lat": 40,
430
+ "rot": 0,
431
+ },
432
+ ),
433
+ # --- LARGE GRID CROSSES GREENWICH, SMALL IS EAST -----------------------
434
+ (
435
+ {
436
+ "nx": 50,
437
+ "ny": 50,
438
+ "size_x": 8000,
439
+ "size_y": 5000,
440
+ "center_lon": -2,
441
+ "center_lat": 40,
442
+ "rot": 0,
443
+ },
444
+ {
445
+ "nx": 10,
446
+ "ny": 10,
447
+ "size_x": 400,
448
+ "size_y": 400,
449
+ "center_lon": 8,
450
+ "center_lat": 40,
451
+ "rot": 0,
452
+ },
453
+ ),
454
+ # --- BOTH GRIDS CROSS GREENWICH ---------------------------------------
455
+ (
456
+ {
457
+ "nx": 60,
458
+ "ny": 60,
459
+ "size_x": 9000,
460
+ "size_y": 6000,
461
+ "center_lon": 1,
462
+ "center_lat": 48,
463
+ "rot": 0,
464
+ },
465
+ {
466
+ "nx": 12,
467
+ "ny": 12,
468
+ "size_x": 900,
469
+ "size_y": 900,
470
+ "center_lon": -1,
471
+ "center_lat": 48,
472
+ "rot": 0,
473
+ },
474
+ ),
475
+ ]
476
+
477
+
478
+ # ----------------------------------------------------------------------
479
+ # THE TEST
480
+ # ----------------------------------------------------------------------
481
+
482
+
483
+ @pytest.mark.parametrize(
484
+ "big_params, small_params",
485
+ grid_cases,
486
+ )
487
+ def test_choose_subdomain_with(big_params, small_params):
488
+ """Tests choose_subdomain() for rho, u, and v points over various grid configurations."""
489
+ # --- build big grid ---
490
+ big = Grid(**big_params)
491
+ ds = xr.Dataset()
492
+ ds = ds.assign_coords(
493
+ {
494
+ "lat_rho": big.ds.lat_rho,
495
+ "lon_rho": big.ds.lon_rho,
496
+ "lat_u": big.ds.lat_u,
497
+ "lon_u": big.ds.lon_u,
498
+ "lat_v": big.ds.lat_v,
499
+ "lon_v": big.ds.lon_v,
500
+ }
501
+ )
502
+
503
+ # simple fields for testing
504
+ ds["field_rho"] = (
505
+ ("eta_rho", "xi_rho"),
506
+ (big.ds["eta_rho"] * big.ds["xi_rho"]).values,
507
+ )
508
+ ds["field_u"] = (("eta_rho", "xi_u"), np.random.rand(*big.ds["lat_u"].shape))
509
+ ds["field_v"] = (("eta_v", "xi_rho"), np.random.rand(*big.ds["lat_v"].shape))
510
+
511
+ # --- build small grid ---
512
+ small = Grid(**small_params)
513
+ target_coords = get_target_coords(small)
514
+
515
+ # --- apply function ---
516
+ sub = choose_subdomain(ds, big.ds, target_coords, buffer_points=1)
517
+
518
+ # --- rho tests ---
519
+ assert sub.lat_rho.shape[0] <= ds.lat_rho.shape[0]
520
+ assert sub.lat_rho.shape[1] <= ds.lat_rho.shape[1]
521
+ assert float(sub.lat_rho.min()) >= float(ds.lat_rho.min()) - 1e-6
522
+ assert float(sub.lat_rho.max()) <= float(ds.lat_rho.max()) + 1e-6
523
+ assert not sub.field_rho.isnull().any()
524
+
525
+ # --- u tests ---
526
+ if "lat_u" in sub.coords and "lon_u" in sub.coords:
527
+ assert sub.lat_u.shape[0] <= ds.lat_u.shape[0]
528
+ assert sub.lat_u.shape[1] <= ds.lat_u.shape[1]
529
+ assert float(sub.lat_u.min()) >= float(ds.lat_u.min()) - 1e-6
530
+ assert float(sub.lat_u.max()) <= float(ds.lat_u.max()) + 1e-6
531
+ assert not sub.field_u.isnull().any()
532
+
533
+ # --- v tests ---
534
+ if "lat_v" in sub.coords and "lon_v" in sub.coords:
535
+ assert sub.lat_v.shape[0] <= ds.lat_v.shape[0]
536
+ assert sub.lat_v.shape[1] <= ds.lat_v.shape[1]
537
+ assert float(sub.lat_v.min()) >= float(ds.lat_v.min()) - 1e-6
538
+ assert float(sub.lat_v.max()) <= float(ds.lat_v.max()) + 1e-6
539
+ assert not sub.field_v.isnull().any()