roms-tools 2.4.0__py3-none-any.whl → 2.6.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 (214) hide show
  1. ci/environment-with-xesmf.yml +16 -0
  2. roms_tools/__init__.py +1 -1
  3. roms_tools/analysis/roms_output.py +339 -234
  4. roms_tools/analysis/utils.py +137 -0
  5. roms_tools/plot.py +353 -214
  6. roms_tools/regrid.py +154 -9
  7. roms_tools/setup/boundary_forcing.py +51 -37
  8. roms_tools/setup/datasets.py +129 -74
  9. roms_tools/setup/grid.py +32 -33
  10. roms_tools/setup/initial_conditions.py +30 -37
  11. roms_tools/setup/nesting.py +238 -64
  12. roms_tools/setup/river_forcing.py +256 -86
  13. roms_tools/setup/surface_forcing.py +40 -28
  14. roms_tools/setup/tides.py +10 -13
  15. roms_tools/setup/topography.py +27 -4
  16. roms_tools/setup/utils.py +28 -12
  17. roms_tools/tests/test_analysis/test_roms_output.py +299 -80
  18. roms_tools/tests/test_regrid.py +85 -2
  19. roms_tools/tests/test_setup/test_boundary_forcing.py +63 -0
  20. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zattrs +3 -1
  21. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zmetadata +3 -1
  22. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_east/0.0.0 +0 -0
  23. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_south/0.0.0 +0 -0
  24. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/0.0.0 +0 -0
  25. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_east/0.0.0 +0 -0
  26. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_south/0.0.0 +0 -0
  27. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/0.0.0 +0 -0
  28. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_east/0.0.0 +0 -0
  29. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_south/0.0.0 +0 -0
  30. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/0.0.0 +0 -0
  31. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_east/0.0.0 +0 -0
  32. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_south/0.0.0 +0 -0
  33. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/0.0.0 +0 -0
  34. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_east/0.0.0 +0 -0
  35. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_south/0.0.0 +0 -0
  36. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/0.0.0 +0 -0
  37. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_east/0.0.0 +0 -0
  38. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_south/0.0.0 +0 -0
  39. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/0.0.0 +0 -0
  40. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_east/0.0.0 +0 -0
  41. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_south/0.0.0 +0 -0
  42. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/0.0.0 +0 -0
  43. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_east/0.0.0 +0 -0
  44. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_south/0.0.0 +0 -0
  45. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/0.0.0 +0 -0
  46. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_east/0.0.0 +0 -0
  47. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_south/0.0.0 +0 -0
  48. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/0.0.0 +0 -0
  49. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_east/0.0.0 +0 -0
  50. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_south/0.0.0 +0 -0
  51. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/0.0.0 +0 -0
  52. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_east/0.0.0 +0 -0
  53. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_south/0.0.0 +0 -0
  54. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/0.0.0 +0 -0
  55. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_east/0.0.0 +0 -0
  56. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_south/0.0.0 +0 -0
  57. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/0.0.0 +0 -0
  58. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_east/0.0.0 +0 -0
  59. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_north/0.0.0 +0 -0
  60. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_south/0.0.0 +0 -0
  61. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/0.0.0 +0 -0
  62. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_east/0.0.0 +0 -0
  63. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_south/0.0.0 +0 -0
  64. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/0.0.0 +0 -0
  65. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_east/0.0.0 +0 -0
  66. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_south/0.0.0 +0 -0
  67. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/0.0.0 +0 -0
  68. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_east/0.0.0 +0 -0
  69. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_south/0.0.0 +0 -0
  70. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/0.0.0 +0 -0
  71. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_east/0.0.0 +0 -0
  72. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_south/0.0.0 +0 -0
  73. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/0.0.0 +0 -0
  74. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_east/0.0.0 +0 -0
  75. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_north/0.0.0 +0 -0
  76. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_south/0.0.0 +0 -0
  77. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/0.0.0 +0 -0
  78. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_east/0.0.0 +0 -0
  79. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_north/0.0.0 +0 -0
  80. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_south/0.0.0 +0 -0
  81. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/0.0.0 +0 -0
  82. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_east/0.0.0 +0 -0
  83. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_north/0.0.0 +0 -0
  84. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_south/0.0.0 +0 -0
  85. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/0.0.0 +0 -0
  86. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_east/0.0.0 +0 -0
  87. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_north/0.0.0 +0 -0
  88. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_south/0.0.0 +0 -0
  89. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/0.0.0 +0 -0
  90. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_east/0.0.0 +0 -0
  91. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_north/0.0.0 +0 -0
  92. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_south/0.0.0 +0 -0
  93. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/0.0.0 +0 -0
  94. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_east/0.0.0 +0 -0
  95. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_north/0.0.0 +0 -0
  96. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_south/0.0.0 +0 -0
  97. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/0.0.0 +0 -0
  98. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_east/0.0.0 +0 -0
  99. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_north/0.0.0 +0 -0
  100. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_south/0.0.0 +0 -0
  101. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/0.0.0 +0 -0
  102. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_east/0.0.0 +0 -0
  103. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_north/0.0.0 +0 -0
  104. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_south/0.0.0 +0 -0
  105. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/0.0.0 +0 -0
  106. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_east/0.0.0 +0 -0
  107. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_north/0.0.0 +0 -0
  108. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_south/0.0.0 +0 -0
  109. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/0.0.0 +0 -0
  110. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_east/0.0.0 +0 -0
  111. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_north/0.0.0 +0 -0
  112. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_south/0.0.0 +0 -0
  113. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/0.0.0 +0 -0
  114. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_east/0.0.0 +0 -0
  115. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_north/0.0.0 +0 -0
  116. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_south/0.0.0 +0 -0
  117. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/0.0.0 +0 -0
  118. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_east/0.0.0 +0 -0
  119. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_north/0.0.0 +0 -0
  120. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_south/0.0.0 +0 -0
  121. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/0.0.0 +0 -0
  122. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_east/0.0.0 +0 -0
  123. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_north/0.0.0 +0 -0
  124. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_south/0.0.0 +0 -0
  125. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/0.0.0 +0 -0
  126. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_east/0.0.0 +0 -0
  127. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_north/0.0.0 +0 -0
  128. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_south/0.0.0 +0 -0
  129. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/0.0.0 +0 -0
  130. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/0.0.0 +0 -0
  131. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_north/0.0.0 +0 -0
  132. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_south/0.0.0 +0 -0
  133. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/0.0.0 +0 -0
  134. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zattrs +2 -2
  135. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zmetadata +8 -7
  136. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/abs_time/.zattrs +1 -0
  137. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/dust/0.0.0 +0 -0
  138. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/dust_time/.zattrs +1 -1
  139. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/iron/0.0.0 +0 -0
  140. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/iron_time/.zattrs +1 -1
  141. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nhy/0.0.0 +0 -0
  142. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nhy_time/.zattrs +1 -1
  143. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nox/0.0.0 +0 -0
  144. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nox_time/.zattrs +1 -1
  145. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air/0.0.0 +0 -0
  146. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air_alt/0.0.0 +0 -0
  147. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_time/.zattrs +1 -1
  148. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zattrs +2 -2
  149. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zmetadata +2 -2
  150. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/dust/0.0.0 +0 -0
  151. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/iron/0.0.0 +0 -0
  152. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nhy/0.0.0 +0 -0
  153. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nox/0.0.0 +0 -0
  154. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air/0.0.0 +0 -0
  155. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air_alt/0.0.0 +0 -0
  156. roms_tools/tests/test_setup/test_data/grid.zarr/.zattrs +1 -1
  157. roms_tools/tests/test_setup/test_data/grid.zarr/.zmetadata +2 -2
  158. roms_tools/tests/test_setup/test_data/grid.zarr/angle/0.0 +0 -0
  159. roms_tools/tests/test_setup/test_data/grid.zarr/angle_coarse/0.0 +0 -0
  160. roms_tools/tests/test_setup/test_data/grid.zarr/f/0.0 +0 -0
  161. roms_tools/tests/test_setup/test_data/grid.zarr/h/.zattrs +1 -1
  162. roms_tools/tests/test_setup/test_data/grid.zarr/h/0.0 +0 -0
  163. roms_tools/tests/test_setup/test_data/grid.zarr/lat_coarse/0.0 +0 -0
  164. roms_tools/tests/test_setup/test_data/grid.zarr/lat_rho/0.0 +0 -0
  165. roms_tools/tests/test_setup/test_data/grid.zarr/lat_u/0.0 +0 -0
  166. roms_tools/tests/test_setup/test_data/grid.zarr/lat_v/0.0 +0 -0
  167. roms_tools/tests/test_setup/test_data/grid.zarr/pm/0.0 +0 -0
  168. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zattrs +1 -1
  169. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zmetadata +1 -1
  170. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/angle/0.0 +0 -0
  171. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/angle_coarse/0.0 +0 -0
  172. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/f/0.0 +0 -0
  173. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/h/0.0 +0 -0
  174. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_coarse/0.0 +0 -0
  175. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_rho/0.0 +0 -0
  176. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_u/0.0 +0 -0
  177. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_v/0.0 +0 -0
  178. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_coarse/0.0 +0 -0
  179. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_rho/0.0 +0 -0
  180. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_u/0.0 +0 -0
  181. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_v/0.0 +0 -0
  182. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/pm/0.0 +0 -0
  183. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/pn/0.0 +0 -0
  184. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zattrs +1 -1
  185. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zmetadata +1 -1
  186. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/salt/0.0.0.0 +0 -0
  187. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/temp/0.0.0.0 +0 -0
  188. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/u/0.0.0.0 +0 -0
  189. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ubar/0.0.0 +0 -0
  190. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/v/0.0.0.0 +0 -0
  191. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/vbar/0.0.0 +0 -0
  192. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zeta/0.0.0 +0 -0
  193. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zmetadata +27 -1
  194. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/nriver/.zarray +20 -0
  195. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/nriver/.zattrs +6 -0
  196. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/nriver/0 +0 -0
  197. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_location/.zattrs +1 -1
  198. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/.zmetadata +27 -1
  199. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/nriver/.zarray +20 -0
  200. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/nriver/.zattrs +6 -0
  201. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/nriver/0 +0 -0
  202. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_location/.zattrs +1 -1
  203. roms_tools/tests/test_setup/test_initial_conditions.py +16 -0
  204. roms_tools/tests/test_setup/test_nesting.py +141 -104
  205. roms_tools/tests/test_setup/test_river_forcing.py +580 -266
  206. roms_tools/tests/test_setup/test_surface_forcing.py +47 -0
  207. roms_tools/tests/test_setup/test_validation.py +34 -2
  208. roms_tools/utils.py +11 -7
  209. roms_tools/vertical_coordinate.py +1 -0
  210. {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info}/METADATA +22 -11
  211. {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info}/RECORD +214 -206
  212. {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info}/WHEEL +1 -1
  213. {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info/licenses}/LICENSE +0 -0
  214. {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info}/top_level.txt +0 -0
roms_tools/regrid.py CHANGED
@@ -1,7 +1,9 @@
1
+ import xgcm
1
2
  import xarray as xr
3
+ import warnings
2
4
 
3
5
 
4
- class LateralRegrid:
6
+ class LateralRegridToROMS:
5
7
  """Handles lateral regridding of data onto a new spatial grid."""
6
8
 
7
9
  def __init__(self, target_coords, source_dim_names):
@@ -49,7 +51,92 @@ class LateralRegrid:
49
51
  return regridded
50
52
 
51
53
 
52
- class VerticalRegrid:
54
+ class LateralRegridFromROMS:
55
+ """Regrids data from a curvilinear ROMS grid onto latitude-longitude coordinates
56
+ using xESMF.
57
+
58
+ It requires the `xesmf` library, which can be installed by installing `roms-tools` via conda.
59
+
60
+ Parameters
61
+ ----------
62
+ source_grid_ds : xarray.Dataset
63
+ The source dataset containing the curvilinear ROMS grid with 'lat_rho' and 'lon_rho'.
64
+
65
+ target_coords : dict
66
+ A dictionary containing 'lat' and 'lon' arrays representing the target
67
+ latitude and longitude coordinates for regridding.
68
+
69
+ method : str, optional
70
+ The regridding method to use. Default is "bilinear". Other options include "nearest_s2d" and "conservative".
71
+
72
+ Raises
73
+ ------
74
+ ImportError
75
+ If xESMF is not installed.
76
+ """
77
+
78
+ def __init__(self, ds_in, target_coords, method="bilinear"):
79
+ """Initializes the regridder with the source and target grids.
80
+
81
+ Parameters
82
+ ----------
83
+ ds_in : xarray.Dataset or xarray.DataArray
84
+ The source dataset or dataarray containing the curvilinear ROMS grid with coordinates 'lat' and 'lon'.
85
+
86
+ target_coords : dict
87
+ A dictionary containing 'lat' and 'lon' arrays representing the target latitude
88
+ and longitude coordinates for regridding.
89
+
90
+ method : str, optional
91
+ The regridding method to use. Default is "bilinear". Other options include
92
+ "nearest_s2d" and "conservative".
93
+
94
+ Raises
95
+ ------
96
+ ImportError
97
+ If xESMF is not installed.
98
+ """
99
+
100
+ try:
101
+ import xesmf as xe
102
+
103
+ except ImportError:
104
+ raise ImportError(
105
+ "xesmf is required for this regridding task. Please install `roms-tools` via conda, which includes xesmf."
106
+ )
107
+
108
+ ds_out = xr.Dataset()
109
+ ds_out["lat"] = target_coords["lat"]
110
+ ds_out["lon"] = target_coords["lon"]
111
+
112
+ with warnings.catch_warnings():
113
+ warnings.filterwarnings("ignore", category=UserWarning, module="xesmf")
114
+ self.regridder = xe.Regridder(
115
+ ds_in, ds_out, method=method, unmapped_to_nan=True
116
+ )
117
+
118
+ def apply(self, da):
119
+ """Applies the regridding to the provided data array.
120
+
121
+ Parameters
122
+ ----------
123
+ da : xarray.DataArray
124
+ The data array to regrid. This should have the same dimension names as the
125
+ source grid (e.g., 'lat' and 'lon').
126
+
127
+ Returns
128
+ -------
129
+ xarray.DataArray
130
+ The regridded data array.
131
+ """
132
+
133
+ with warnings.catch_warnings():
134
+ warnings.filterwarnings("ignore", category=UserWarning, module="xesmf")
135
+ regridded = self.regridder(da, keep_attrs=True)
136
+ return regridded
137
+
138
+
139
+ class VerticalRegridToROMS:
53
140
  """Interpolates data onto new vertical (depth) coordinates.
54
141
 
55
142
  Parameters
@@ -106,13 +193,13 @@ class VerticalRegrid:
106
193
  }
107
194
  )
108
195
 
109
- def apply(self, var, fill_nans=True):
196
+ def apply(self, da, fill_nans=True):
110
197
  """Interpolates the variable onto the new depth grid using precomputed
111
198
  coefficients for linear interpolation between layers.
112
199
 
113
200
  Parameters
114
201
  ----------
115
- var : xarray.DataArray
202
+ da : xarray.DataArray
116
203
  The input data to be regridded along the depth dimension. This should be
117
204
  an array with the same depth coordinates as the original grid.
118
205
  fill_nans : bool, optional
@@ -130,16 +217,74 @@ class VerticalRegrid:
130
217
 
131
218
  dims = {"dim": self.depth_dim}
132
219
 
133
- var_below = var.where(self.coeff["is_below"]).sum(**dims)
134
- var_above = var.where(self.coeff["is_above"]).sum(**dims)
220
+ da_below = da.where(self.coeff["is_below"]).sum(**dims)
221
+ da_above = da.where(self.coeff["is_above"]).sum(**dims)
135
222
 
136
- result = var_below + (var_above - var_below) * self.coeff["factor"]
223
+ result = da_below + (da_above - da_below) * self.coeff["factor"]
137
224
  if fill_nans:
138
- result = result.where(self.coeff["upper_mask"], var.isel({dims["dim"]: 0}))
139
- result = result.where(self.coeff["lower_mask"], var.isel({dims["dim"]: -1}))
225
+ result = result.where(self.coeff["upper_mask"], da.isel({dims["dim"]: 0}))
226
+ result = result.where(self.coeff["lower_mask"], da.isel({dims["dim"]: -1}))
140
227
  else:
141
228
  result = result.where(self.coeff["upper_mask"]).where(
142
229
  self.coeff["lower_mask"]
143
230
  )
144
231
 
145
232
  return result
233
+
234
+
235
+ class VerticalRegridFromROMS:
236
+ """A class for regridding data from the ROMS vertical coordinate system to target
237
+ depth levels.
238
+
239
+ This class uses the `xgcm` package to perform the transformation from the ROMS depth coordinates to
240
+ a user-defined set of target depth levels. It assumes that the input dataset `ds` contains the necessary
241
+ vertical coordinate information (`s_rho`).
242
+
243
+ Attributes
244
+ ----------
245
+ grid : xgcm.Grid
246
+ The grid object used for regridding, initialized with the given dataset `ds`.
247
+ """
248
+
249
+ def __init__(self, ds):
250
+ """Initializes the `VerticalRegridFromROMS` object by creating an `xgcm.Grid`
251
+ instance.
252
+
253
+ Parameters
254
+ ----------
255
+ ds : xarray.Dataset
256
+ The dataset containing the ROMS output data, which must include the vertical coordinate `s_rho`.
257
+ """
258
+ self.grid = xgcm.Grid(ds, coords={"s_rho": {"center": "s_rho"}}, periodic=False)
259
+
260
+ def apply(self, da, depth_coords, target_depth_levels):
261
+ """Applies vertical regridding from ROMS to the specified target depth levels.
262
+
263
+ This method transforms the input data array `da` from the ROMS vertical coordinate (`s_rho`)
264
+ to a set of target depth levels defined by `target_depth_levels`.
265
+
266
+ Parameters
267
+ ----------
268
+ da : xarray.DataArray
269
+ The data array containing the ROMS output field to be regridded. It must have a vertical
270
+ dimension corresponding to `s_rho`.
271
+
272
+ depth_coords : array-like
273
+ The depth coordinates of the input data array `da` (typically the `s_rho` coordinate in ROMS).
274
+
275
+ target_depth_levels : array-like
276
+ The target depth levels to which the input data `da` will be regridded.
277
+
278
+ Returns
279
+ -------
280
+ xarray.DataArray
281
+ A new `xarray.DataArray` containing the regridded data at the specified target depth levels.
282
+ """
283
+
284
+ with warnings.catch_warnings():
285
+ warnings.filterwarnings("ignore", category=FutureWarning, module="xgcm")
286
+ transformed = self.grid.transform(
287
+ da, "s_rho", target_depth_levels, target_data=depth_coords
288
+ )
289
+
290
+ return transformed
@@ -3,13 +3,13 @@ import numpy as np
3
3
  from scipy.ndimage import label
4
4
  import logging
5
5
  import importlib.metadata
6
- from typing import Dict, Union, List
6
+ from typing import Dict, Union, List, Optional
7
7
  from dataclasses import dataclass, field
8
8
  from datetime import datetime
9
9
  import matplotlib.pyplot as plt
10
10
  from pathlib import Path
11
11
  from roms_tools import Grid
12
- from roms_tools.regrid import LateralRegrid, VerticalRegrid
12
+ from roms_tools.regrid import LateralRegridToROMS, VerticalRegridToROMS
13
13
  from roms_tools.utils import save_datasets
14
14
  from roms_tools.vertical_coordinate import compute_depth
15
15
  from roms_tools.plot import _section_plot, _line_plot
@@ -35,7 +35,7 @@ from roms_tools.setup.utils import (
35
35
  )
36
36
 
37
37
 
38
- @dataclass(frozen=True, kw_only=True)
38
+ @dataclass(kw_only=True)
39
39
  class BoundaryForcing:
40
40
  """Represents boundary forcing input data for ROMS.
41
41
 
@@ -43,10 +43,14 @@ class BoundaryForcing:
43
43
  ----------
44
44
  grid : Grid
45
45
  Object representing the grid information.
46
- start_time : datetime
47
- Start time of the desired boundary forcing data.
48
- end_time : datetime
49
- End time of the desired boundary forcing data.
46
+ start_time : datetime, optional
47
+ The start time of the desired surface forcing data. This time is used to filter the dataset
48
+ to include only records on or after this time, with a single record at or before this time.
49
+ If no time filtering is desired, set it to None. Default is None.
50
+ end_time : datetime, optional
51
+ The end time of the desired surface forcing data. This time is used to filter the dataset
52
+ to include only records on or before this time, with a single record at or after this time.
53
+ If no time filtering is desired, set it to None. Default is None.
50
54
  boundaries : Dict[str, bool], optional
51
55
  Dictionary specifying which boundaries are forced (south, east, north, west). Default is all True.
52
56
  source : Dict[str, Union[str, Path, List[Union[str, Path]]], bool]
@@ -96,8 +100,8 @@ class BoundaryForcing:
96
100
  """
97
101
 
98
102
  grid: Grid
99
- start_time: datetime
100
- end_time: datetime
103
+ start_time: Optional[datetime] = None
104
+ end_time: Optional[datetime] = None
101
105
  boundaries: Dict[str, bool] = field(
102
106
  default_factory=lambda: {
103
107
  "south": True,
@@ -120,17 +124,20 @@ class BoundaryForcing:
120
124
 
121
125
  self._input_checks()
122
126
  # Dataset for depth coordinates
123
- object.__setattr__(self, "ds_depth_coords", xr.Dataset())
127
+ self.ds_depth_coords = xr.Dataset()
124
128
 
125
129
  target_coords = get_target_coords(self.grid)
126
130
 
127
131
  data = self._get_data()
128
132
 
129
133
  if self.apply_2d_horizontal_fill:
134
+
130
135
  data.choose_subdomain(
131
136
  target_coords,
132
137
  buffer_points=20, # lateral fill needs good buffer from data margin
133
138
  )
139
+ # Enforce double precision to ensure reproducibility
140
+ data.convert_to_float64()
134
141
  data.extrapolate_deepest_to_bottom()
135
142
  data.apply_lateral_fill()
136
143
 
@@ -158,6 +165,8 @@ class BoundaryForcing:
158
165
  )
159
166
 
160
167
  if not self.apply_2d_horizontal_fill:
168
+ # Enforce double precision to ensure reproducibility
169
+ bdry_data.convert_to_float64()
161
170
  bdry_data.extrapolate_deepest_to_bottom()
162
171
 
163
172
  processed_fields = {}
@@ -176,7 +185,7 @@ class BoundaryForcing:
176
185
  lat = target_coords["lat"].isel(
177
186
  **self.bdry_coords["vector"][direction]
178
187
  )
179
- lateral_regrid = LateralRegrid(
188
+ lateral_regrid = LateralRegridToROMS(
180
189
  {"lat": lat, "lon": lon}, bdry_data.dim_names
181
190
  )
182
191
  for var_name in vector_var_names:
@@ -205,7 +214,7 @@ class BoundaryForcing:
205
214
  lat = target_coords["lat"].isel(
206
215
  **self.bdry_coords["rho"][direction]
207
216
  )
208
- lateral_regrid = LateralRegrid(
217
+ lateral_regrid = LateralRegridToROMS(
209
218
  {"lat": lat, "lon": lon}, bdry_data.dim_names
210
219
  )
211
220
  for var_name in tracer_var_names:
@@ -283,7 +292,7 @@ class BoundaryForcing:
283
292
  # vertical regridding
284
293
  for location in ["rho", "u", "v"]:
285
294
  if len(var_names_dict[location]) > 0:
286
- vertical_regrid = VerticalRegrid(
295
+ vertical_regrid = VerticalRegridToROMS(
287
296
  self.ds_depth_coords[f"layer_depth_{location}_{direction}"],
288
297
  bdry_data.ds[bdry_data.dim_names["depth"]],
289
298
  )
@@ -326,9 +335,21 @@ class BoundaryForcing:
326
335
  for var_name in ds.data_vars:
327
336
  ds[var_name] = substitute_nans_by_fillvalue(ds[var_name])
328
337
 
329
- object.__setattr__(self, "ds", ds)
338
+ self.ds = ds
330
339
 
331
340
  def _input_checks(self):
341
+ # Check that start_time and end_time are both None or none of them is
342
+ if (self.start_time is None) != (self.end_time is None):
343
+ raise ValueError(
344
+ "Both `start_time` and `end_time` must be provided together as datetime objects or both should be None."
345
+ )
346
+
347
+ # Trigger a warning if both are None
348
+ if self.start_time is None and self.end_time is None:
349
+ logging.warning(
350
+ "Both `start_time` and `end_time` are None. No time filtering will be applied to the source data."
351
+ )
352
+
332
353
  # Validate the 'type' parameter
333
354
  if self.type not in ["physics", "bgc"]:
334
355
  raise ValueError("`type` must be either 'physics' or 'bgc'.")
@@ -340,11 +361,10 @@ class BoundaryForcing:
340
361
  raise ValueError("`source` must include a 'path'.")
341
362
 
342
363
  # Set 'climatology' to False if not provided in 'source'
343
- object.__setattr__(
344
- self,
345
- "source",
346
- {**self.source, "climatology": self.source.get("climatology", False)},
347
- )
364
+ self.source = {
365
+ **self.source,
366
+ "climatology": self.source.get("climatology", False),
367
+ }
348
368
 
349
369
  # Ensure adjust_depth_for_sea_surface_height is only used with type="physics"
350
370
  if self.type == "bgc" and self.adjust_depth_for_sea_surface_height:
@@ -352,7 +372,7 @@ class BoundaryForcing:
352
372
  "adjust_depth_for_sea_surface_height is not applicable for BGC fields. "
353
373
  "Setting it to False."
354
374
  )
355
- object.__setattr__(self, "adjust_depth_for_sea_surface_height", False)
375
+ self.adjust_depth_for_sea_surface_height = False
356
376
  elif self.adjust_depth_for_sea_surface_height:
357
377
  logging.info("Sea surface height will be used to adjust depth coordinates.")
358
378
  else:
@@ -474,7 +494,7 @@ class BoundaryForcing:
474
494
  else:
475
495
  variable_info[var_name] = {**default_info, "validate": False}
476
496
 
477
- object.__setattr__(self, "variable_info", variable_info)
497
+ self.variable_info = variable_info
478
498
 
479
499
  def _write_into_dataset(self, direction, processed_fields, ds=None):
480
500
  if ds is None:
@@ -542,7 +562,7 @@ class BoundaryForcing:
542
562
 
543
563
  bdry_coords = get_boundary_coords()
544
564
 
545
- object.__setattr__(self, "bdry_coords", bdry_coords)
565
+ self.bdry_coords = bdry_coords
546
566
 
547
567
  def _get_depth_coordinates(
548
568
  self,
@@ -840,12 +860,6 @@ class BoundaryForcing:
840
860
 
841
861
  field = self.ds[var_name].isel(bry_time=time)
842
862
 
843
- if self.use_dask:
844
- from dask.diagnostics import ProgressBar
845
-
846
- with ProgressBar():
847
- field = field.load()
848
-
849
863
  title = field.long_name
850
864
  var_name_wo_direction, direction = var_name.split("_")
851
865
  location = self.variable_info[var_name_wo_direction]["location"]
@@ -860,10 +874,17 @@ class BoundaryForcing:
860
874
 
861
875
  mask = mask.isel(**self.bdry_coords[location][direction])
862
876
 
877
+ # Load the data
878
+ if self.use_dask:
879
+ from dask.diagnostics import ProgressBar
880
+
881
+ with ProgressBar():
882
+ field = field.load()
883
+
863
884
  if "s_rho" in field.dims:
864
885
  layer_depth = self.ds_depth_coords[f"layer_depth_{location}_{direction}"]
865
886
  if self.adjust_depth_for_sea_surface_height:
866
- layer_depth = layer_depth.isel(time=time)
887
+ layer_depth = layer_depth.isel(time=time).load()
867
888
  field = field.assign_coords({"layer_depth": layer_depth})
868
889
  if var_name.startswith(("u", "v", "ubar", "vbar", "zeta")):
869
890
  vmax = max(field.max().values, -field.min().values)
@@ -967,7 +988,6 @@ class BoundaryForcing:
967
988
  cls,
968
989
  filepath: Union[str, Path],
969
990
  use_dask: bool = False,
970
- bypass_validation: bool = False,
971
991
  ) -> "BoundaryForcing":
972
992
  """Create an instance of the BoundaryForcing class from a YAML file.
973
993
 
@@ -977,10 +997,6 @@ class BoundaryForcing:
977
997
  The path to the YAML file from which the parameters will be read.
978
998
  use_dask: bool, optional
979
999
  Indicates whether to use dask for processing. If True, data is processed with dask; if False, data is processed eagerly. Defaults to False.
980
- bypass_validation: bool, optional
981
- Indicates whether to skip validation checks in the processed data. When set to True,
982
- the validation process that ensures no NaN values exist at wet points
983
- in the processed dataset is bypassed. Defaults to False.
984
1000
 
985
1001
  Returns
986
1002
  -------
@@ -993,9 +1009,7 @@ class BoundaryForcing:
993
1009
  params = _from_yaml(cls, filepath)
994
1010
 
995
1011
  # Create and return an instance of InitialConditions
996
- return cls(
997
- grid=grid, **params, use_dask=use_dask, bypass_validation=bypass_validation
998
- )
1012
+ return cls(grid=grid, **params, use_dask=use_dask)
999
1013
 
1000
1014
 
1001
1015
  def apply_1d_horizontal_fill(data_array: xr.DataArray) -> xr.DataArray: