roms-tools 1.6.2__py3-none-any.whl → 2.0.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 (283) hide show
  1. ci/environment.yml +1 -1
  2. roms_tools/__init__.py +1 -0
  3. roms_tools/_version.py +1 -1
  4. roms_tools/setup/boundary_forcing.py +266 -256
  5. roms_tools/setup/datasets.py +986 -231
  6. roms_tools/setup/download.py +41 -15
  7. roms_tools/setup/grid.py +561 -512
  8. roms_tools/setup/initial_conditions.py +162 -106
  9. roms_tools/setup/mask.py +69 -0
  10. roms_tools/setup/plot.py +81 -23
  11. roms_tools/setup/regrid.py +4 -2
  12. roms_tools/setup/river_forcing.py +589 -0
  13. roms_tools/setup/surface_forcing.py +21 -130
  14. roms_tools/setup/tides.py +15 -79
  15. roms_tools/setup/topography.py +92 -128
  16. roms_tools/setup/utils.py +307 -25
  17. roms_tools/setup/vertical_coordinate.py +5 -16
  18. roms_tools/tests/test_setup/test_boundary_forcing.py +10 -7
  19. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zattrs +1 -1
  20. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zmetadata +157 -130
  21. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_east/.zattrs +1 -1
  22. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_north/.zattrs +1 -1
  23. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_south/.zattrs +1 -1
  24. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/.zattrs +1 -1
  25. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_east/.zattrs +1 -1
  26. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_north/.zattrs +1 -1
  27. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_south/.zattrs +1 -1
  28. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/.zattrs +1 -1
  29. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_east/.zattrs +1 -1
  30. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_north/.zattrs +1 -1
  31. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_south/.zattrs +1 -1
  32. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/.zattrs +1 -1
  33. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_east/.zattrs +1 -1
  34. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_north/.zattrs +1 -1
  35. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_south/.zattrs +1 -1
  36. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/.zattrs +1 -1
  37. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_east/.zattrs +1 -1
  38. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_north/.zattrs +1 -1
  39. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_south/.zattrs +1 -1
  40. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/.zattrs +1 -1
  41. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_east/.zattrs +1 -1
  42. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_north/.zattrs +1 -1
  43. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_south/.zattrs +1 -1
  44. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/.zattrs +1 -1
  45. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_east/.zattrs +1 -1
  46. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_north/.zattrs +1 -1
  47. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_south/.zattrs +1 -1
  48. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/.zattrs +1 -1
  49. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_east/.zattrs +1 -1
  50. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_north/.zattrs +1 -1
  51. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_south/.zattrs +1 -1
  52. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/.zattrs +1 -1
  53. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_east/.zattrs +1 -1
  54. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_north/.zattrs +1 -1
  55. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_south/.zattrs +1 -1
  56. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/.zattrs +1 -1
  57. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_east/.zattrs +1 -1
  58. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_north/.zattrs +1 -1
  59. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_south/.zattrs +1 -1
  60. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/.zattrs +1 -1
  61. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_east/.zattrs +1 -1
  62. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_north/.zattrs +1 -1
  63. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_south/.zattrs +1 -1
  64. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/.zattrs +1 -1
  65. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_east/.zattrs +1 -1
  66. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_north/.zattrs +1 -1
  67. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_south/.zattrs +1 -1
  68. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/.zattrs +1 -1
  69. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_east/.zattrs +1 -1
  70. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_north/.zattrs +1 -1
  71. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_south/.zattrs +1 -1
  72. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/.zattrs +1 -1
  73. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_east/.zattrs +1 -1
  74. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_north/.zattrs +1 -1
  75. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_south/.zattrs +1 -1
  76. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/.zattrs +1 -1
  77. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_east/.zattrs +1 -1
  78. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_north/.zattrs +1 -1
  79. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_south/.zattrs +1 -1
  80. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/.zattrs +1 -1
  81. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_east/.zattrs +1 -1
  82. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_north/.zattrs +1 -1
  83. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_south/.zattrs +1 -1
  84. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/.zattrs +1 -1
  85. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_east/.zattrs +1 -1
  86. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_north/.zattrs +1 -1
  87. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_south/.zattrs +1 -1
  88. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/.zattrs +1 -1
  89. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/abs_time/.zattrs +1 -0
  90. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/bry_time/.zattrs +1 -1
  91. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_east/.zattrs +1 -1
  92. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_north/.zattrs +1 -1
  93. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_south/.zattrs +1 -1
  94. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/.zattrs +1 -1
  95. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_east/.zattrs +1 -1
  96. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_north/.zattrs +1 -1
  97. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_south/.zattrs +1 -1
  98. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/.zattrs +1 -1
  99. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_east/.zattrs +1 -1
  100. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_north/.zattrs +1 -1
  101. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_south/.zattrs +1 -1
  102. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/.zattrs +1 -1
  103. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_east/.zattrs +1 -1
  104. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_north/.zattrs +1 -1
  105. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_south/.zattrs +1 -1
  106. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/.zattrs +1 -1
  107. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_east/.zattrs +1 -1
  108. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_north/.zattrs +1 -1
  109. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_south/.zattrs +1 -1
  110. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/.zattrs +1 -1
  111. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_east/.zattrs +1 -1
  112. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_north/.zattrs +1 -1
  113. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_south/.zattrs +1 -1
  114. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/.zattrs +1 -1
  115. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_east/.zattrs +1 -1
  116. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_north/.zattrs +1 -1
  117. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_south/.zattrs +1 -1
  118. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/.zattrs +1 -1
  119. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_east/.zattrs +1 -1
  120. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_north/.zattrs +1 -1
  121. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_south/.zattrs +1 -1
  122. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/.zattrs +1 -1
  123. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_east/.zattrs +1 -1
  124. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_north/.zattrs +1 -1
  125. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_south/.zattrs +1 -1
  126. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/.zattrs +1 -1
  127. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/month/.zarray +20 -0
  128. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/month/.zattrs +6 -0
  129. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/month/0 +0 -0
  130. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_east/.zattrs +1 -1
  131. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_north/.zattrs +1 -1
  132. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_south/.zattrs +1 -1
  133. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/.zattrs +1 -1
  134. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_east/.zattrs +1 -1
  135. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_north/.zattrs +1 -1
  136. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_south/.zattrs +1 -1
  137. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/.zattrs +1 -1
  138. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_east/.zattrs +1 -1
  139. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_north/.zattrs +1 -1
  140. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_south/.zattrs +1 -1
  141. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/.zattrs +1 -1
  142. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_east/.zattrs +1 -1
  143. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_north/.zattrs +1 -1
  144. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_south/.zattrs +1 -1
  145. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/.zattrs +1 -1
  146. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_east/.zattrs +1 -1
  147. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_north/.zattrs +1 -1
  148. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_south/.zattrs +1 -1
  149. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/.zattrs +1 -1
  150. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/.zattrs +1 -1
  151. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_north/.zattrs +1 -1
  152. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_south/.zattrs +1 -1
  153. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/.zattrs +1 -1
  154. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zattrs +1 -1
  155. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zmetadata +39 -12
  156. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/abs_time/.zattrs +1 -0
  157. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/dust/.zattrs +1 -1
  158. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/dust_time/.zattrs +1 -1
  159. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/iron/.zattrs +1 -1
  160. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/iron_time/.zattrs +1 -1
  161. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/month/.zarray +20 -0
  162. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/month/.zattrs +6 -0
  163. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/month/0 +0 -0
  164. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nhy/.zattrs +1 -1
  165. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nhy_time/.zattrs +1 -1
  166. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nox/.zattrs +1 -1
  167. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nox_time/.zattrs +1 -1
  168. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air/.zattrs +1 -1
  169. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air_alt/.zattrs +1 -1
  170. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_time/.zattrs +1 -1
  171. roms_tools/tests/test_setup/test_data/grid.zarr/.zattrs +0 -1
  172. roms_tools/tests/test_setup/test_data/grid.zarr/.zmetadata +56 -201
  173. roms_tools/tests/test_setup/test_data/grid.zarr/Cs_r/.zattrs +1 -1
  174. roms_tools/tests/test_setup/test_data/grid.zarr/Cs_w/.zattrs +1 -1
  175. roms_tools/tests/test_setup/test_data/grid.zarr/{interface_depth_rho → sigma_r}/.zarray +2 -6
  176. roms_tools/tests/test_setup/test_data/grid.zarr/sigma_r/.zattrs +7 -0
  177. roms_tools/tests/test_setup/test_data/grid.zarr/sigma_r/0 +0 -0
  178. roms_tools/tests/test_setup/test_data/grid.zarr/{interface_depth_u → sigma_w}/.zarray +2 -6
  179. roms_tools/tests/test_setup/test_data/grid.zarr/sigma_w/.zattrs +7 -0
  180. roms_tools/tests/test_setup/test_data/grid.zarr/sigma_w/0 +0 -0
  181. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zattrs +1 -2
  182. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zmetadata +58 -203
  183. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/Cs_r/.zattrs +1 -1
  184. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/Cs_w/.zattrs +1 -1
  185. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/h/.zattrs +1 -1
  186. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/h/0.0 +0 -0
  187. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_coarse/0.0 +0 -0
  188. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_rho/0.0 +0 -0
  189. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_u/0.0 +0 -0
  190. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/mask_v/0.0 +0 -0
  191. roms_tools/tests/test_setup/test_data/{grid.zarr/interface_depth_v → grid_that_straddles_dateline.zarr/sigma_r}/.zarray +2 -6
  192. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/sigma_r/.zattrs +7 -0
  193. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/sigma_r/0 +0 -0
  194. roms_tools/tests/test_setup/test_data/{grid.zarr/layer_depth_rho → grid_that_straddles_dateline.zarr/sigma_w}/.zarray +2 -6
  195. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/sigma_w/.zattrs +7 -0
  196. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/sigma_w/0 +0 -0
  197. roms_tools/tests/test_setup/test_data/river_forcing.zarr/.zattrs +3 -0
  198. roms_tools/tests/test_setup/test_data/river_forcing.zarr/.zgroup +3 -0
  199. roms_tools/tests/test_setup/test_data/river_forcing.zarr/.zmetadata +214 -0
  200. roms_tools/tests/test_setup/test_data/river_forcing.zarr/abs_time/.zarray +20 -0
  201. roms_tools/tests/test_setup/test_data/river_forcing.zarr/abs_time/.zattrs +8 -0
  202. roms_tools/tests/test_setup/test_data/river_forcing.zarr/abs_time/0 +0 -0
  203. roms_tools/tests/test_setup/test_data/river_forcing.zarr/month/.zarray +20 -0
  204. roms_tools/tests/test_setup/test_data/river_forcing.zarr/month/.zattrs +6 -0
  205. roms_tools/tests/test_setup/test_data/river_forcing.zarr/month/0 +0 -0
  206. roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_name/.zarray +24 -0
  207. roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_name/.zattrs +6 -0
  208. roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_name/0 +0 -0
  209. roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_time/.zarray +20 -0
  210. roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_time/.zattrs +8 -0
  211. roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_time/0 +0 -0
  212. roms_tools/tests/test_setup/test_data/{grid.zarr/layer_depth_v → river_forcing.zarr/river_tracer}/.zarray +4 -4
  213. roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_tracer/.zattrs +10 -0
  214. roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_tracer/0.0.0 +0 -0
  215. roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_volume/.zarray +22 -0
  216. roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_volume/.zattrs +9 -0
  217. roms_tools/tests/test_setup/test_data/river_forcing.zarr/river_volume/0.0 +0 -0
  218. roms_tools/tests/test_setup/test_data/{grid.zarr/layer_depth_u → river_forcing.zarr/tracer_name}/.zarray +2 -6
  219. roms_tools/tests/test_setup/test_data/river_forcing.zarr/tracer_name/.zattrs +6 -0
  220. roms_tools/tests/test_setup/test_data/river_forcing.zarr/tracer_name/0 +0 -0
  221. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zattrs +1 -0
  222. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zgroup +3 -0
  223. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zmetadata +185 -0
  224. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/abs_time/.zarray +20 -0
  225. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/abs_time/.zattrs +8 -0
  226. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/abs_time/0 +0 -0
  227. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_name/.zarray +24 -0
  228. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_name/.zattrs +6 -0
  229. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_name/0 +0 -0
  230. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_time/.zarray +20 -0
  231. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_time/.zattrs +7 -0
  232. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_time/0 +0 -0
  233. roms_tools/tests/test_setup/test_data/{grid_that_straddles_dateline.zarr/interface_depth_v → river_forcing_no_climatology.zarr/river_tracer}/.zarray +4 -4
  234. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_tracer/.zattrs +10 -0
  235. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_tracer/0.0.0 +0 -0
  236. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_volume/.zarray +22 -0
  237. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_volume/.zattrs +9 -0
  238. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_volume/0.0 +0 -0
  239. roms_tools/tests/test_setup/test_data/{grid_that_straddles_dateline.zarr/interface_depth_u → river_forcing_no_climatology.zarr/tracer_name}/.zarray +2 -6
  240. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_name/.zattrs +6 -0
  241. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_name/0 +0 -0
  242. roms_tools/tests/test_setup/test_grid.py +110 -12
  243. roms_tools/tests/test_setup/test_initial_conditions.py +2 -3
  244. roms_tools/tests/test_setup/test_river_forcing.py +367 -0
  245. roms_tools/tests/test_setup/test_surface_forcing.py +2 -24
  246. roms_tools/tests/test_setup/test_tides.py +2 -3
  247. roms_tools/tests/test_setup/test_topography.py +106 -1
  248. roms_tools/tests/test_setup/test_validation.py +4 -0
  249. roms_tools/utils.py +12 -10
  250. {roms_tools-1.6.2.dist-info → roms_tools-2.0.0.dist-info}/LICENSE +1 -1
  251. {roms_tools-1.6.2.dist-info → roms_tools-2.0.0.dist-info}/METADATA +6 -5
  252. {roms_tools-1.6.2.dist-info → roms_tools-2.0.0.dist-info}/RECORD +254 -225
  253. {roms_tools-1.6.2.dist-info → roms_tools-2.0.0.dist-info}/WHEEL +1 -1
  254. roms_tools/tests/test_setup/test_data/grid.zarr/interface_depth_rho/.zattrs +0 -9
  255. roms_tools/tests/test_setup/test_data/grid.zarr/interface_depth_rho/0.0.0 +0 -0
  256. roms_tools/tests/test_setup/test_data/grid.zarr/interface_depth_u/.zattrs +0 -9
  257. roms_tools/tests/test_setup/test_data/grid.zarr/interface_depth_u/0.0.0 +0 -0
  258. roms_tools/tests/test_setup/test_data/grid.zarr/interface_depth_v/.zattrs +0 -9
  259. roms_tools/tests/test_setup/test_data/grid.zarr/interface_depth_v/0.0.0 +0 -0
  260. roms_tools/tests/test_setup/test_data/grid.zarr/layer_depth_rho/.zattrs +0 -9
  261. roms_tools/tests/test_setup/test_data/grid.zarr/layer_depth_rho/0.0.0 +0 -0
  262. roms_tools/tests/test_setup/test_data/grid.zarr/layer_depth_u/.zattrs +0 -9
  263. roms_tools/tests/test_setup/test_data/grid.zarr/layer_depth_u/0.0.0 +0 -0
  264. roms_tools/tests/test_setup/test_data/grid.zarr/layer_depth_v/.zattrs +0 -9
  265. roms_tools/tests/test_setup/test_data/grid.zarr/layer_depth_v/0.0.0 +0 -0
  266. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/interface_depth_rho/.zarray +0 -24
  267. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/interface_depth_rho/.zattrs +0 -9
  268. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/interface_depth_rho/0.0.0 +0 -0
  269. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/interface_depth_u/.zattrs +0 -9
  270. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/interface_depth_u/0.0.0 +0 -0
  271. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/interface_depth_v/.zattrs +0 -9
  272. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/interface_depth_v/0.0.0 +0 -0
  273. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/layer_depth_rho/.zarray +0 -24
  274. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/layer_depth_rho/.zattrs +0 -9
  275. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/layer_depth_rho/0.0.0 +0 -0
  276. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/layer_depth_u/.zarray +0 -24
  277. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/layer_depth_u/.zattrs +0 -9
  278. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/layer_depth_u/0.0.0 +0 -0
  279. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/layer_depth_v/.zarray +0 -24
  280. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/layer_depth_v/.zattrs +0 -9
  281. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/layer_depth_v/0.0.0 +0 -0
  282. roms_tools/tests/test_setup/test_vertical_coordinate.py +0 -91
  283. {roms_tools-1.6.2.dist-info → roms_tools-2.0.0.dist-info}/top_level.txt +0 -0
@@ -1,12 +1,12 @@
1
1
  import xarray as xr
2
2
  import numpy as np
3
- import yaml
4
3
  import importlib.metadata
5
- from dataclasses import dataclass, field, asdict
4
+ from dataclasses import dataclass, field
6
5
  from typing import Dict, Union, List, Optional
7
6
  from roms_tools.setup.grid import Grid
8
7
  from datetime import datetime
9
8
  from roms_tools.setup.datasets import GLORYSDataset, CESMBGCDataset
9
+ from roms_tools.setup.vertical_coordinate import compute_depth
10
10
  from roms_tools.setup.utils import (
11
11
  nan_check,
12
12
  substitute_nans_by_fillvalue,
@@ -16,6 +16,10 @@ from roms_tools.setup.utils import (
16
16
  rotate_velocities,
17
17
  compute_barotropic_velocity,
18
18
  transpose_dimensions,
19
+ interpolate_from_rho_to_u,
20
+ interpolate_from_rho_to_v,
21
+ _to_yaml,
22
+ _from_yaml,
19
23
  )
20
24
  from roms_tools.setup.regrid import LateralRegrid, VerticalRegrid
21
25
  from roms_tools.setup.plot import _plot, _section_plot, _profile_plot, _line_plot
@@ -91,23 +95,17 @@ class InitialConditions:
91
95
  self._input_checks()
92
96
 
93
97
  processed_fields = {}
94
- processed_fields, variable_info = self._process_data(
95
- processed_fields, type="physics"
96
- )
98
+ processed_fields = self._process_data(processed_fields, type="physics")
97
99
 
98
100
  if self.bgc_source is not None:
99
- processed_fields, bgc_variable_info = self._process_data(
100
- processed_fields, type="bgc"
101
- )
101
+ processed_fields = self._process_data(processed_fields, type="bgc")
102
102
 
103
103
  d_meta = get_variable_metadata()
104
104
  ds = self._write_into_dataset(processed_fields, d_meta)
105
105
 
106
106
  ds = self._add_global_metadata(ds)
107
107
 
108
- if self.bgc_source is not None:
109
- variable_info = {**variable_info, **bgc_variable_info}
110
- self._validate(ds, variable_info)
108
+ self._validate(ds)
111
109
 
112
110
  # substitute NaNs over land by a fill value to avoid blow-up of ROMS
113
111
  for var_name in ds.data_vars:
@@ -132,7 +130,9 @@ class InitialConditions:
132
130
  data.extrapolate_deepest_to_bottom()
133
131
  data.apply_lateral_fill()
134
132
 
135
- variable_info = self._set_variable_info(data, type=type)
133
+ self._set_variable_info(data, type=type)
134
+ attr_name = f"variable_info_{type}"
135
+ variable_info = getattr(self, attr_name)
136
136
  var_names = variable_info.keys()
137
137
 
138
138
  # lateral regridding
@@ -152,19 +152,31 @@ class InitialConditions:
152
152
  interpolate=True,
153
153
  )
154
154
 
155
- # vertical regridding
155
+ var_names_dict = {}
156
156
  for location in ["rho", "u", "v"]:
157
- var_names = [
157
+ var_names_dict[location] = [
158
158
  name
159
159
  for name, info in variable_info.items()
160
160
  if info["location"] == location and info["is_3d"]
161
161
  ]
162
- if len(var_names) > 0:
162
+
163
+ # compute layer depth coordinates
164
+ if len(var_names_dict["u"]) > 0 or len(var_names_dict["v"]) > 0:
165
+ self._get_vertical_coordinates(
166
+ type="layer",
167
+ additional_locations=["u", "v"],
168
+ )
169
+ else:
170
+ if len(var_names_dict["rho"]) > 0:
171
+ self._get_vertical_coordinates(type="layer", additional_locations=[])
172
+ # vertical regridding
173
+ for location in ["rho", "u", "v"]:
174
+ if len(var_names_dict[location]) > 0:
163
175
  vertical_regrid = VerticalRegrid(
164
176
  self.grid.ds[f"layer_depth_{location}"],
165
177
  data.ds[data.dim_names["depth"]],
166
178
  )
167
- for var_name in var_names:
179
+ for var_name in var_names_dict[location]:
168
180
  if var_name in processed_fields:
169
181
  processed_fields[var_name] = vertical_regrid.apply(
170
182
  processed_fields[var_name]
@@ -172,10 +184,14 @@ class InitialConditions:
172
184
 
173
185
  # compute barotropic velocities
174
186
  if "u" in variable_info and "v" in variable_info:
175
- for var_name in ["u", "v"]:
176
- processed_fields[f"{var_name}bar"] = compute_barotropic_velocity(
177
- processed_fields[var_name],
178
- self.grid.ds[f"interface_depth_{var_name}"],
187
+ self._get_vertical_coordinates(
188
+ type="interface",
189
+ additional_locations=["u", "v"],
190
+ )
191
+ for location in ["u", "v"]:
192
+ processed_fields[f"{location}bar"] = compute_barotropic_velocity(
193
+ processed_fields[location],
194
+ self.grid.ds[f"interface_depth_{location}"],
179
195
  )
180
196
 
181
197
  if type == "bgc":
@@ -190,7 +206,7 @@ class InitialConditions:
190
206
  processed_fields[var_name]
191
207
  )
192
208
 
193
- return processed_fields, variable_info
209
+ return processed_fields
194
210
 
195
211
  def _input_checks(self):
196
212
 
@@ -344,7 +360,84 @@ class InitialConditions:
344
360
  else:
345
361
  variable_info[var_name] = {**default_info, "validate": False}
346
362
 
347
- return variable_info
363
+ object.__setattr__(self, f"variable_info_{type}", variable_info)
364
+
365
+ def _get_vertical_coordinates(self, type, additional_locations=["u", "v"]):
366
+ """Retrieve layer and interface depth coordinates.
367
+
368
+ This method computes and updates the layer and interface depth coordinates. It handles depth calculations for rho points and
369
+ additional specified locations (u and v).
370
+
371
+ Parameters
372
+ ----------
373
+ type : str
374
+ The type of depth coordinate to retrieve. Valid options are:
375
+ - "layer": Retrieves layer depth coordinates.
376
+ - "interface": Retrieves interface depth coordinates.
377
+
378
+ additional_locations : list of str, optional
379
+ Specifies additional locations to compute depth coordinates for. Default is ["u", "v"].
380
+ Valid options include:
381
+ - "u": Computes depth coordinates for u points.
382
+ - "v": Computes depth coordinates for v points.
383
+
384
+ Updates
385
+ -------
386
+ self.grid.ds : xarray.Dataset
387
+ The dataset is updated with the following vertical depth coordinates:
388
+ - f"{type}_depth_rho": Depth coordinates at rho points.
389
+ - f"{type}_depth_u": Depth coordinates at u points (if applicable).
390
+ - f"{type}_depth_v": Depth coordinates at v points (if applicable).
391
+ """
392
+
393
+ layer_vars = []
394
+ for location in ["rho"] + additional_locations:
395
+ layer_vars.append(f"{type}_depth_{location}")
396
+
397
+ if all(layer_var in self.grid.ds for layer_var in layer_vars):
398
+ # Vertical coordinate data already exists
399
+ pass
400
+
401
+ elif f"{type}_depth_rho" in self.grid.ds:
402
+ depth = self.grid.ds[f"{type}_depth_rho"]
403
+
404
+ if "u" in additional_locations or "v" in additional_locations:
405
+ # interpolation
406
+ if "u" in additional_locations:
407
+ depth_u = interpolate_from_rho_to_u(depth)
408
+ depth_u.attrs["long_name"] = f"{type} depth at u-points"
409
+ depth_u.attrs["units"] = "m"
410
+ self.grid.ds[f"{type}_depth_u"] = depth_u
411
+ if "v" in additional_locations:
412
+ depth_v = interpolate_from_rho_to_v(depth)
413
+ depth_v.attrs["long_name"] = f"{type} depth at v-points"
414
+ depth_v.attrs["units"] = "m"
415
+ self.grid.ds[f"{type}_depth_v"] = depth_v
416
+ else:
417
+ h = self.grid.ds["h"]
418
+ if type == "layer":
419
+ depth = compute_depth(
420
+ 0, h, self.grid.hc, self.grid.ds.Cs_r, self.grid.ds.sigma_r
421
+ )
422
+ else:
423
+ depth = compute_depth(
424
+ 0, h, self.grid.hc, self.grid.ds.Cs_w, self.grid.ds.sigma_w
425
+ )
426
+
427
+ depth.attrs["long_name"] = f"{type} depth at rho-points"
428
+ depth.attrs["units"] = "m"
429
+ self.grid.ds[f"{type}_depth_rho"] = depth
430
+
431
+ if "u" in additional_locations or "v" in additional_locations:
432
+ # interpolation
433
+ depth_u = interpolate_from_rho_to_u(depth)
434
+ depth_u.attrs["long_name"] = f"{type} depth at u-points"
435
+ depth_u.attrs["units"] = "m"
436
+ depth_v = interpolate_from_rho_to_v(depth)
437
+ depth_v.attrs["long_name"] = f"{type} depth at v-points"
438
+ depth_v.attrs["units"] = "m"
439
+ self.grid.ds[f"{type}_depth_u"] = depth_u
440
+ self.grid.ds[f"{type}_depth_v"] = depth_v
348
441
 
349
442
  def _write_into_dataset(self, processed_fields, d_meta):
350
443
 
@@ -387,24 +480,29 @@ class InitialConditions:
387
480
  ds["Cs_w"] = self.grid.ds["Cs_w"]
388
481
 
389
482
  # Preserve absolute time coordinate for readability
390
- ds = ds.assign_coords({"abs_time": ds["time"]})
483
+ abs_time = ds["time"]
484
+ attrs = [key for key in abs_time.attrs]
485
+ for attr in attrs:
486
+ del abs_time.attrs[attr]
487
+ abs_time.attrs["long_name"] = "absolute time"
488
+ ds = ds.assign_coords({"abs_time": abs_time})
391
489
 
392
490
  # Translate the time coordinate to days since the model reference date
393
491
  model_reference_date = np.datetime64(self.model_reference_date)
394
492
 
395
- # Convert the time coordinate to the format expected by ROMS (days since model reference date)
493
+ # Convert the time coordinate to the format expected by ROMS (seconds since model reference date)
396
494
  ocean_time = (ds["time"] - model_reference_date).astype("float64") * 1e-9
397
495
  ds = ds.assign_coords(ocean_time=("time", ocean_time.data.astype("float64")))
398
496
  ds["ocean_time"].attrs[
399
497
  "long_name"
400
- ] = f"seconds since {str(self.model_reference_date)}"
498
+ ] = f"relative time: seconds since {str(self.model_reference_date)}"
401
499
  ds["ocean_time"].attrs["units"] = "seconds"
402
500
  ds = ds.swap_dims({"time": "ocean_time"})
403
501
  ds = ds.drop_vars("time")
404
502
 
405
503
  return ds
406
504
 
407
- def _validate(self, ds, variable_info):
505
+ def _validate(self, ds):
408
506
  """Validates the dataset by checking for NaN values in SSH at wet points, which
409
507
  would indicate missing raw data coverage over the target domain.
410
508
 
@@ -412,8 +510,6 @@ class InitialConditions:
412
510
  ----------
413
511
  ds : xarray.Dataset
414
512
  The dataset to validate.
415
- variable_info : dict
416
- A dictionary containing metadata about the variables, including whether to validate them.
417
513
 
418
514
  Raises
419
515
  ------
@@ -425,6 +521,10 @@ class InitialConditions:
425
521
  -----
426
522
  This check is only applied to the 2D variable SSH to improve performance.
427
523
  """
524
+ if self.bgc_source is not None:
525
+ variable_info = {**self.variable_info_physics, **self.variable_info_bgc}
526
+ else:
527
+ variable_info = self.variable_info_physics
428
528
 
429
529
  for var_name in variable_info:
430
530
  # Only validate variables based on "validate" flag if use_dask is False
@@ -564,9 +664,17 @@ class InitialConditions:
564
664
  self.ds[var_name].load()
565
665
 
566
666
  field = self.ds[var_name].squeeze()
667
+ if s is not None:
668
+ layer_contours = False
567
669
 
568
670
  if all(dim in field.dims for dim in ["eta_rho", "xi_rho"]):
569
- interface_depth = self.grid.ds.interface_depth_rho
671
+ if layer_contours:
672
+ if "interface_depth_rho" in self.grid.ds:
673
+ interface_depth = self.grid.ds.interface_depth_rho
674
+ else:
675
+ self.get_vertical_coordinates(
676
+ type="interface", additional_locations=[]
677
+ )
570
678
  layer_depth = self.grid.ds.layer_depth_rho
571
679
  mask = self.grid.ds.mask_rho
572
680
  field = field.assign_coords(
@@ -574,7 +682,13 @@ class InitialConditions:
574
682
  )
575
683
 
576
684
  elif all(dim in field.dims for dim in ["eta_rho", "xi_u"]):
577
- interface_depth = self.grid.ds.interface_depth_u
685
+ if layer_contours:
686
+ if "interface_depth_u" in self.grid.ds:
687
+ interface_depth = self.grid.ds.interface_depth_u
688
+ else:
689
+ self.get_vertical_coordinates(
690
+ type="interface", additional_locations=["u", "v"]
691
+ )
578
692
  layer_depth = self.grid.ds.layer_depth_u
579
693
  mask = self.grid.ds.mask_u
580
694
  field = field.assign_coords(
@@ -582,7 +696,13 @@ class InitialConditions:
582
696
  )
583
697
 
584
698
  elif all(dim in field.dims for dim in ["eta_v", "xi_rho"]):
585
- interface_depth = self.grid.ds.interface_depth_v
699
+ if layer_contours:
700
+ if "interface_depth_v" in self.grid.ds:
701
+ interface_depth = self.grid.ds.interface_depth_v
702
+ else:
703
+ self.get_vertical_coordinates(
704
+ type="interface", additional_locations=["u", "v"]
705
+ )
586
706
  layer_depth = self.grid.ds.layer_depth_v
587
707
  mask = self.grid.ds.mask_v
588
708
  field = field.assign_coords(
@@ -606,14 +726,16 @@ class InitialConditions:
606
726
  title = title + f", eta_rho = {field.eta_rho[eta].item()}"
607
727
  field = field.isel(eta_rho=eta)
608
728
  layer_depth = layer_depth.isel(eta_rho=eta)
609
- interface_depth = interface_depth.isel(eta_rho=eta)
729
+ if layer_contours:
730
+ interface_depth = interface_depth.isel(eta_rho=eta)
610
731
  if "s_rho" in field.dims:
611
732
  field = field.assign_coords({"layer_depth": layer_depth})
612
733
  elif "eta_v" in field.dims:
613
734
  title = title + f", eta_v = {field.eta_v[eta].item()}"
614
735
  field = field.isel(eta_v=eta)
615
736
  layer_depth = layer_depth.isel(eta_v=eta)
616
- interface_depth = interface_depth.isel(eta_v=eta)
737
+ if layer_contours:
738
+ interface_depth = interface_depth.isel(eta_v=eta)
617
739
  if "s_rho" in field.dims:
618
740
  field = field.assign_coords({"layer_depth": layer_depth})
619
741
  else:
@@ -625,14 +747,16 @@ class InitialConditions:
625
747
  title = title + f", xi_rho = {field.xi_rho[xi].item()}"
626
748
  field = field.isel(xi_rho=xi)
627
749
  layer_depth = layer_depth.isel(xi_rho=xi)
628
- interface_depth = interface_depth.isel(xi_rho=xi)
750
+ if layer_contours:
751
+ interface_depth = interface_depth.isel(xi_rho=xi)
629
752
  if "s_rho" in field.dims:
630
753
  field = field.assign_coords({"layer_depth": layer_depth})
631
754
  elif "xi_u" in field.dims:
632
755
  title = title + f", xi_u = {field.xi_u[xi].item()}"
633
756
  field = field.isel(xi_u=xi)
634
757
  layer_depth = layer_depth.isel(xi_u=xi)
635
- interface_depth = interface_depth.isel(xi_u=xi)
758
+ if layer_contours:
759
+ interface_depth = interface_depth.isel(xi_u=xi)
636
760
  if "s_rho" in field.dims:
637
761
  field = field.assign_coords({"layer_depth": layer_depth})
638
762
  else:
@@ -753,48 +877,8 @@ class InitialConditions:
753
877
  filepath : Union[str, Path]
754
878
  The path to the YAML file where the parameters will be saved.
755
879
  """
756
- filepath = Path(filepath)
757
-
758
- # Serialize Grid data
759
- grid_data = asdict(self.grid)
760
- grid_data.pop("ds", None) # Exclude non-serializable fields
761
- grid_data.pop("straddle", None)
762
-
763
- # Include the version of roms-tools
764
- try:
765
- roms_tools_version = importlib.metadata.version("roms-tools")
766
- except importlib.metadata.PackageNotFoundError:
767
- roms_tools_version = "unknown"
768
-
769
- # Create header
770
- header = f"---\nroms_tools_version: {roms_tools_version}\n---\n"
771
-
772
- grid_yaml_data = {"Grid": grid_data}
773
880
 
774
- initial_conditions_data = {
775
- "InitialConditions": {
776
- "ini_time": self.ini_time.isoformat(),
777
- "source": self.source,
778
- }
779
- }
780
- # Include bgc_source if it's not None
781
- if self.bgc_source is not None:
782
- initial_conditions_data["InitialConditions"]["bgc_source"] = self.bgc_source
783
-
784
- initial_conditions_data["InitialConditions"][
785
- "model_reference_date"
786
- ] = self.model_reference_date.isoformat()
787
-
788
- yaml_data = {
789
- **grid_yaml_data,
790
- **initial_conditions_data,
791
- }
792
-
793
- with filepath.open("w") as file:
794
- # Write header
795
- file.write(header)
796
- # Write YAML data
797
- yaml.dump(yaml_data, file, default_flow_style=False, sort_keys=False)
881
+ _to_yaml(self, filepath)
798
882
 
799
883
  @classmethod
800
884
  def from_yaml(
@@ -815,35 +899,7 @@ class InitialConditions:
815
899
  An instance of the InitialConditions class.
816
900
  """
817
901
  filepath = Path(filepath)
818
- # Read the entire file content
819
- with filepath.open("r") as file:
820
- file_content = file.read()
821
-
822
- # Split the content into YAML documents
823
- documents = list(yaml.safe_load_all(file_content))
824
-
825
- initial_conditions_data = None
826
-
827
- # Process the YAML documents
828
- for doc in documents:
829
- if doc is None:
830
- continue
831
- if "InitialConditions" in doc:
832
- initial_conditions_data = doc["InitialConditions"]
833
- break
834
-
835
- if initial_conditions_data is None:
836
- raise ValueError(
837
- "No InitialConditions configuration found in the YAML file."
838
- )
839
-
840
- # Convert from string to datetime
841
- for date_string in ["model_reference_date", "ini_time"]:
842
- initial_conditions_data[date_string] = datetime.fromisoformat(
843
- initial_conditions_data[date_string]
844
- )
845
902
 
846
903
  grid = Grid.from_yaml(filepath)
847
-
848
- # Create and return an instance of InitialConditions
849
- return cls(grid=grid, **initial_conditions_data, use_dask=use_dask)
904
+ initial_conditions_params = _from_yaml(cls, filepath)
905
+ return cls(grid=grid, **initial_conditions_params, use_dask=use_dask)
@@ -0,0 +1,69 @@
1
+ import xarray as xr
2
+ import numpy as np
3
+ import regionmask
4
+ from scipy.ndimage import label
5
+ from roms_tools.setup.utils import (
6
+ interpolate_from_rho_to_u,
7
+ interpolate_from_rho_to_v,
8
+ handle_boundaries,
9
+ )
10
+
11
+
12
+ def _add_mask(ds):
13
+
14
+ land = regionmask.defined_regions.natural_earth_v5_0_0.land_10
15
+
16
+ land_mask = land.mask(ds["lon_rho"], ds["lat_rho"])
17
+ mask = land_mask.isnull()
18
+
19
+ # fill enclosed basins with land
20
+ mask = _fill_enclosed_basins(mask.values)
21
+ # adjust mask boundaries by copying values from adjacent cells
22
+ mask = handle_boundaries(mask)
23
+
24
+ ds["mask_rho"] = xr.DataArray(mask.astype(np.int32), dims=("eta_rho", "xi_rho"))
25
+ ds["mask_rho"].attrs = {
26
+ "long_name": "Mask at rho-points",
27
+ "units": "land/water (0/1)",
28
+ }
29
+ ds = _add_velocity_masks(ds)
30
+
31
+ return ds
32
+
33
+
34
+ def _fill_enclosed_basins(mask) -> np.ndarray:
35
+ """Fills in enclosed basins with land."""
36
+
37
+ # Label connected regions in the mask
38
+ reg, nreg = label(mask)
39
+ # Find the largest region
40
+ lint = 0
41
+ lreg = 0
42
+ for ireg in range(nreg):
43
+ int_ = np.sum(reg == ireg)
44
+ if int_ > lint and mask[reg == ireg].sum() > 0:
45
+ lreg = ireg
46
+ lint = int_
47
+
48
+ # Remove regions other than the largest one
49
+ for ireg in range(nreg):
50
+ if ireg != lreg:
51
+ mask[reg == ireg] = 0
52
+
53
+ return mask
54
+
55
+
56
+ def _add_velocity_masks(ds):
57
+
58
+ # add u- and v-masks
59
+ ds["mask_u"] = interpolate_from_rho_to_u(
60
+ ds["mask_rho"], method="multiplicative"
61
+ ).astype(np.int32)
62
+ ds["mask_v"] = interpolate_from_rho_to_v(
63
+ ds["mask_rho"], method="multiplicative"
64
+ ).astype(np.int32)
65
+
66
+ ds["mask_u"].attrs = {"long_name": "Mask at u-points", "units": "land/water (0/1)"}
67
+ ds["mask_v"].attrs = {"long_name": "Mask at v-points", "units": "land/water (0/1)"}
68
+
69
+ return ds
roms_tools/setup/plot.py CHANGED
@@ -58,16 +58,71 @@ def _plot(
58
58
  if straddle:
59
59
  lon_deg = xr.where(lon_deg > 180, lon_deg - 360, lon_deg)
60
60
 
61
- # Define projections
62
- proj = ccrs.PlateCarree()
63
-
64
- trans = ccrs.NearsidePerspective(
65
- central_longitude=lon_deg.mean().values, central_latitude=lat_deg.mean().values
66
- )
61
+ trans = _get_projection(lon_deg, lat_deg)
67
62
 
68
63
  lon_deg = lon_deg.values
69
64
  lat_deg = lat_deg.values
70
65
 
66
+ fig, ax = plt.subplots(1, 1, figsize=(13, 7), subplot_kw={"projection": trans})
67
+
68
+ _add_plot_to_ax(
69
+ ax, lon_deg, lat_deg, trans, field, depth_contours, c, title, kwargs=kwargs
70
+ )
71
+
72
+
73
+ def _add_plot_to_ax(
74
+ ax,
75
+ lon_deg,
76
+ lat_deg,
77
+ trans,
78
+ field=None,
79
+ depth_contours=False,
80
+ c="red",
81
+ title="",
82
+ add_colorbar=True,
83
+ kwargs=None,
84
+ ):
85
+ """Plots a grid or field on a map with optional depth contours.
86
+
87
+ Parameters
88
+ ----------
89
+ ax : matplotlib.axes._axes.Axes
90
+ The axes on which to plot the data (Cartopy axis with projection).
91
+
92
+ lon_deg : np.ndarray
93
+ Longitude values in degrees.
94
+
95
+ lat_deg : np.ndarray
96
+ Latitude values in degrees.
97
+
98
+ trans : cartopy.crs.Projection
99
+ The projection for transforming coordinates.
100
+
101
+ field : xarray.DataArray, optional
102
+ Field data to plot (e.g., temperature, salinity). If None, only the grid is plotted.
103
+
104
+ depth_contours : bool, optional
105
+ If True, adds depth contours to the plot.
106
+
107
+ c : str, optional
108
+ Color of the grid boundary (default is 'red').
109
+
110
+ title : str, optional
111
+ Title of the plot.
112
+
113
+ add_colorbar : bool, optional
114
+ If True, add colobar.
115
+
116
+ kwargs : dict, optional
117
+ Additional keyword arguments passed to `pcolormesh` (e.g., colormap, limits).
118
+
119
+ Notes
120
+ -----
121
+ - If `field` is provided, a colorbar is added.
122
+ - If `depth_contours` is True, the field’s `layer_depth` is used to add contours.
123
+ """
124
+ proj = ccrs.PlateCarree()
125
+
71
126
  # find corners
72
127
  corners = [
73
128
  (lon_deg[0, 0], lat_deg[0, 0]),
@@ -80,14 +135,13 @@ def _plot(
80
135
  transformed_corners = [trans.transform_point(lo, la, proj) for lo, la in corners]
81
136
  transformed_lons, transformed_lats = zip(*transformed_corners)
82
137
 
83
- fig, ax = plt.subplots(1, 1, figsize=(13, 7), subplot_kw={"projection": trans})
84
-
85
- ax.plot(
86
- list(transformed_lons) + [transformed_lons[0]],
87
- list(transformed_lats) + [transformed_lats[0]],
88
- "o-",
89
- c=c,
90
- )
138
+ if c is not None:
139
+ ax.plot(
140
+ list(transformed_lons) + [transformed_lons[0]],
141
+ list(transformed_lats) + [transformed_lats[0]],
142
+ "o-",
143
+ c=c,
144
+ )
91
145
 
92
146
  ax.coastlines(
93
147
  resolution="50m", linewidth=0.5, color="black"
@@ -104,13 +158,21 @@ def _plot(
104
158
  label = f"{field.Long_name} [{field.units}]"
105
159
  else:
106
160
  label = ""
107
- plt.colorbar(p, label=label)
161
+ if add_colorbar:
162
+ plt.colorbar(p, label=label)
108
163
 
109
164
  if depth_contours:
110
165
  cs = ax.contour(lon_deg, lat_deg, field.layer_depth, transform=proj, colors="k")
111
166
  ax.clabel(cs, inline=True, fontsize=10)
112
167
 
113
168
 
169
+ def _get_projection(lon, lat):
170
+
171
+ return ccrs.NearsidePerspective(
172
+ central_longitude=lon.mean().values, central_latitude=lat.mean().values
173
+ )
174
+
175
+
114
176
  def _section_plot(field, interface_depth=None, title="", kwargs={}, ax=None):
115
177
 
116
178
  if ax is None:
@@ -176,18 +238,14 @@ def _profile_plot(field, title="", ax=None):
176
238
  """
177
239
 
178
240
  depths_to_check = [
179
- "layer_depth_rho",
180
- "layer_depth_u",
181
- "layer_depth_v",
182
- "interface_depth_rho",
183
- "interface_depth_u",
184
- "interface_depth_v",
241
+ "layer_depth",
242
+ "interface_depth",
185
243
  ]
186
244
  try:
187
245
  depth_label = next(
188
246
  depth_label
189
- for depth_label in depths_to_check
190
- if depth_label in field.coords
247
+ for depth_label in field.coords
248
+ if any(depth_label.startswith(prefix) for prefix in depths_to_check)
191
249
  )
192
250
  except StopIteration:
193
251
  raise ValueError(
@@ -28,20 +28,22 @@ class LateralRegrid:
28
28
  source_dim_names["longitude"]: target_coords["lon"],
29
29
  }
30
30
 
31
- def apply(self, da):
31
+ def apply(self, da, method="linear"):
32
32
  """Fills missing values and regrids the variable.
33
33
 
34
34
  Parameters
35
35
  ----------
36
36
  da : xarray.DataArray
37
37
  Input data to fill and regrid.
38
+ method : str
39
+ Interpolation method to use.
38
40
 
39
41
  Returns
40
42
  -------
41
43
  xarray.DataArray
42
44
  Regridded data with filled values.
43
45
  """
44
- regridded = da.interp(self.coords, method="linear").drop_vars(
46
+ regridded = da.interp(self.coords, method=method).drop_vars(
45
47
  list(self.coords.keys())
46
48
  )
47
49
  return regridded