roms-tools 1.4.2__py3-none-any.whl → 1.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 (278) hide show
  1. roms_tools/_version.py +1 -1
  2. roms_tools/setup/boundary_forcing.py +448 -130
  3. roms_tools/setup/datasets.py +186 -52
  4. roms_tools/setup/fill.py +2 -2
  5. roms_tools/setup/initial_conditions.py +217 -70
  6. roms_tools/setup/regrid.py +143 -0
  7. roms_tools/setup/surface_forcing.py +159 -73
  8. roms_tools/setup/tides.py +141 -54
  9. roms_tools/setup/utils.py +229 -62
  10. roms_tools/tests/test_setup/test_boundary_forcing.py +42 -32
  11. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zattrs +1 -1
  12. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zmetadata +1 -1
  13. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_east/0.0.0 +0 -0
  14. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_north/0.0.0 +0 -0
  15. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_south/0.0.0 +0 -0
  16. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/0.0.0 +0 -0
  17. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_east/0.0.0 +0 -0
  18. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_north/0.0.0 +0 -0
  19. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_south/0.0.0 +0 -0
  20. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/0.0.0 +0 -0
  21. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_east/0.0.0 +0 -0
  22. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_north/0.0.0 +0 -0
  23. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_south/0.0.0 +0 -0
  24. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/0.0.0 +0 -0
  25. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_east/0.0.0 +0 -0
  26. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_north/0.0.0 +0 -0
  27. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_south/0.0.0 +0 -0
  28. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/0.0.0 +0 -0
  29. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_east/0.0.0 +0 -0
  30. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_north/0.0.0 +0 -0
  31. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_south/0.0.0 +0 -0
  32. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/0.0.0 +0 -0
  33. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_east/0.0.0 +0 -0
  34. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_north/0.0.0 +0 -0
  35. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_south/0.0.0 +0 -0
  36. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/0.0.0 +0 -0
  37. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_east/0.0.0 +0 -0
  38. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_north/0.0.0 +0 -0
  39. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_south/0.0.0 +0 -0
  40. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/0.0.0 +0 -0
  41. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_east/0.0.0 +0 -0
  42. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_north/0.0.0 +0 -0
  43. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_south/0.0.0 +0 -0
  44. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/0.0.0 +0 -0
  45. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_east/0.0.0 +0 -0
  46. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_north/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_north/0.0.0 +0 -0
  51. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_south/0.0.0 +0 -0
  52. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/0.0.0 +0 -0
  53. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_east/0.0.0 +0 -0
  54. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_north/0.0.0 +0 -0
  55. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_south/0.0.0 +0 -0
  56. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/0.0.0 +0 -0
  57. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_east/0.0.0 +0 -0
  58. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_north/0.0.0 +0 -0
  59. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_south/0.0.0 +0 -0
  60. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/0.0.0 +0 -0
  61. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_east/0.0.0 +0 -0
  62. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_north/0.0.0 +0 -0
  63. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_south/0.0.0 +0 -0
  64. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/0.0.0 +0 -0
  65. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_east/0.0.0 +0 -0
  66. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_north/0.0.0 +0 -0
  67. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_south/0.0.0 +0 -0
  68. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/0.0.0 +0 -0
  69. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_east/0.0.0 +0 -0
  70. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_north/0.0.0 +0 -0
  71. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_south/0.0.0 +0 -0
  72. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/0.0.0 +0 -0
  73. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_east/0.0.0 +0 -0
  74. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_north/0.0.0 +0 -0
  75. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_south/0.0.0 +0 -0
  76. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/0.0.0 +0 -0
  77. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_east/0.0.0 +0 -0
  78. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_north/0.0.0 +0 -0
  79. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_south/0.0.0 +0 -0
  80. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/0.0.0 +0 -0
  81. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_east/0.0.0 +0 -0
  82. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_north/0.0.0 +0 -0
  83. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_south/0.0.0 +0 -0
  84. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/0.0.0 +0 -0
  85. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_east/0.0.0 +0 -0
  86. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_north/0.0.0 +0 -0
  87. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_south/0.0.0 +0 -0
  88. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/0.0.0 +0 -0
  89. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_east/0.0.0 +0 -0
  90. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_north/0.0.0 +0 -0
  91. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_south/0.0.0 +0 -0
  92. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/0.0.0 +0 -0
  93. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_east/0.0.0 +0 -0
  94. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_north/0.0.0 +0 -0
  95. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_south/0.0.0 +0 -0
  96. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/0.0.0 +0 -0
  97. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_east/0.0.0 +0 -0
  98. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_north/0.0.0 +0 -0
  99. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_south/0.0.0 +0 -0
  100. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/0.0.0 +0 -0
  101. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_east/0.0.0 +0 -0
  102. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_north/0.0.0 +0 -0
  103. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_south/0.0.0 +0 -0
  104. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/0.0.0 +0 -0
  105. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_east/0.0.0 +0 -0
  106. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_north/0.0.0 +0 -0
  107. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_south/0.0.0 +0 -0
  108. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/0.0.0 +0 -0
  109. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_east/0.0.0 +0 -0
  110. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_north/0.0.0 +0 -0
  111. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_south/0.0.0 +0 -0
  112. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/0.0.0 +0 -0
  113. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_east/0.0.0 +0 -0
  114. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_north/0.0.0 +0 -0
  115. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_south/0.0.0 +0 -0
  116. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/0.0.0 +0 -0
  117. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_east/0.0.0 +0 -0
  118. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_north/0.0.0 +0 -0
  119. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_south/0.0.0 +0 -0
  120. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/0.0.0 +0 -0
  121. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_east/0.0.0 +0 -0
  122. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_north/0.0.0 +0 -0
  123. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_south/0.0.0 +0 -0
  124. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/0.0.0 +0 -0
  125. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_east/0.0.0 +0 -0
  126. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_north/0.0.0 +0 -0
  127. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_south/0.0.0 +0 -0
  128. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/0.0.0 +0 -0
  129. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_east/0.0.0 +0 -0
  130. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_north/0.0.0 +0 -0
  131. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_south/0.0.0 +0 -0
  132. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/0.0.0 +0 -0
  133. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_east/0.0.0 +0 -0
  134. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_north/0.0.0 +0 -0
  135. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_south/0.0.0 +0 -0
  136. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/0.0.0 +0 -0
  137. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/0.0.0 +0 -0
  138. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_north/0.0.0 +0 -0
  139. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_south/0.0.0 +0 -0
  140. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/0.0.0 +0 -0
  141. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zattrs +1 -1
  142. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zmetadata +1 -1
  143. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/dust/0.0.0 +0 -0
  144. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/iron/0.0.0 +0 -0
  145. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nhy/0.0.0 +0 -0
  146. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nox/0.0.0 +0 -0
  147. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air/0.0.0 +0 -0
  148. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air_alt/0.0.0 +0 -0
  149. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zattrs +1 -1
  150. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zmetadata +1 -1
  151. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/dust/0.0.0 +0 -0
  152. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/iron/0.0.0 +0 -0
  153. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nhy/0.0.0 +0 -0
  154. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nox/0.0.0 +0 -0
  155. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air/0.0.0 +0 -0
  156. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air_alt/0.0.0 +0 -0
  157. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zattrs +1 -1
  158. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zmetadata +8 -1
  159. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/.zattrs +3 -0
  160. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_east/0.0.0 +0 -0
  161. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_north/0.0.0 +0 -0
  162. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/0.0.0 +0 -0
  163. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_west/0.0.0 +0 -0
  164. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/0.0.0 +0 -0
  165. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_north/0.0.0 +0 -0
  166. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/0.0.0 +0 -0
  167. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_west/0.0.0 +0 -0
  168. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/0.0.0 +0 -0
  169. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_north/0.0.0 +0 -0
  170. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/0.0.0 +0 -0
  171. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/0.0 +0 -0
  172. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_north/0.0 +0 -0
  173. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/0.0 +0 -0
  174. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/0.0.0 +0 -0
  175. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/0.0.0 +0 -0
  176. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/0.0.0 +0 -0
  177. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/0.0.0 +0 -0
  178. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/0.0 +0 -0
  179. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/0.0 +0 -0
  180. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/0.0 +0 -0
  181. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/0.0 +0 -0
  182. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/.zattrs +1 -0
  183. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/0.0 +0 -0
  184. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_north/.zattrs +1 -0
  185. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/.zattrs +1 -0
  186. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/0.0 +0 -0
  187. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_west/.zattrs +1 -0
  188. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/.zattrs +1 -1
  189. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/.zmetadata +1 -1
  190. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/Tair/0.0.0 +0 -0
  191. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/lwrad/0.0.0 +0 -0
  192. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/qair/0.0.0 +0 -0
  193. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/rain/0.0.0 +0 -0
  194. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/swrad/0.0.0 +0 -0
  195. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/uwnd/0.0.0 +0 -0
  196. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/vwnd/0.0.0 +0 -0
  197. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/.zattrs +1 -1
  198. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/.zmetadata +1 -1
  199. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/Tair/0.0.0 +0 -0
  200. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/lwrad/0.0.0 +0 -0
  201. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/qair/0.0.0 +0 -0
  202. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/rain/0.0.0 +0 -0
  203. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/swrad/0.0.0 +0 -0
  204. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/uwnd/0.0.0 +0 -0
  205. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/vwnd/0.0.0 +0 -0
  206. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zattrs +1 -1
  207. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zmetadata +1 -1
  208. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK/0.0.0.0 +0 -0
  209. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK_ALT_CO2/0.0.0.0 +0 -0
  210. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC/0.0.0.0 +0 -0
  211. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC_ALT_CO2/0.0.0.0 +0 -0
  212. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOC/0.0.0.0 +0 -0
  213. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOCr/0.0.0.0 +0 -0
  214. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DON/0.0.0.0 +0 -0
  215. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DONr/0.0.0.0 +0 -0
  216. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOP/0.0.0.0 +0 -0
  217. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOPr/0.0.0.0 +0 -0
  218. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Fe/0.0.0.0 +0 -0
  219. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Lig/0.0.0.0 +0 -0
  220. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NH4/0.0.0.0 +0 -0
  221. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NO3/0.0.0.0 +0 -0
  222. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/O2/0.0.0.0 +0 -0
  223. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/PO4/0.0.0.0 +0 -0
  224. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/SiO3/0.0.0.0 +0 -0
  225. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatC/0.0.0.0 +0 -0
  226. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatChl/0.0.0.0 +0 -0
  227. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatFe/0.0.0.0 +0 -0
  228. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatP/0.0.0.0 +0 -0
  229. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatSi/0.0.0.0 +0 -0
  230. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazC/0.0.0.0 +0 -0
  231. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazChl/0.0.0.0 +0 -0
  232. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazFe/0.0.0.0 +0 -0
  233. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazP/0.0.0.0 +0 -0
  234. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/salt/0.0.0.0 +0 -0
  235. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spC/0.0.0.0 +0 -0
  236. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spCaCO3/0.0.0.0 +0 -0
  237. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spChl/0.0.0.0 +0 -0
  238. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spFe/0.0.0.0 +0 -0
  239. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spP/0.0.0.0 +0 -0
  240. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/temp/0.0.0.0 +0 -0
  241. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/u/0.0.0.0 +0 -0
  242. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ubar/0.0.0 +0 -0
  243. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/v/0.0.0.0 +0 -0
  244. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/vbar/0.0.0 +0 -0
  245. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zeta/0.0.0 +0 -0
  246. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zooC/0.0.0.0 +0 -0
  247. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/.zattrs +1 -1
  248. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/.zmetadata +1 -1
  249. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/Tair/0.0.0 +0 -0
  250. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/lwrad/0.0.0 +0 -0
  251. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/qair/0.0.0 +0 -0
  252. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/rain/0.0.0 +0 -0
  253. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/swrad/0.0.0 +0 -0
  254. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/uwnd/0.0.0 +0 -0
  255. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/vwnd/0.0.0 +0 -0
  256. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/.zattrs +1 -1
  257. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/.zmetadata +4 -2
  258. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/omega/.zattrs +3 -1
  259. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/pot_Im/0.0.0 +0 -0
  260. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/pot_Re/0.0.0 +0 -0
  261. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ssh_Im/0.0.0 +0 -0
  262. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ssh_Re/0.0.0 +0 -0
  263. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Im/0.0.0 +0 -0
  264. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Re/0.0.0 +0 -0
  265. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Im/0.0.0 +0 -0
  266. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Re/0.0.0 +0 -0
  267. roms_tools/tests/test_setup/test_datasets.py +79 -21
  268. roms_tools/tests/test_setup/test_fill.py +55 -113
  269. roms_tools/tests/test_setup/test_initial_conditions.py +21 -21
  270. roms_tools/tests/test_setup/test_regrid.py +53 -0
  271. roms_tools/tests/test_setup/test_surface_forcing.py +21 -3
  272. roms_tools/tests/test_setup/test_tides.py +1 -1
  273. {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/METADATA +13 -4
  274. {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/RECORD +277 -276
  275. {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/WHEEL +1 -1
  276. roms_tools/setup/mixins.py +0 -227
  277. {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/LICENSE +0 -0
  278. {roms_tools-1.4.2.dist-info → roms_tools-1.6.0.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,7 @@ from roms_tools.setup.grid import Grid
7
7
  from datetime import datetime
8
8
  import numpy as np
9
9
  from typing import Dict, Union, List
10
- from roms_tools.setup.mixins import ROMSToolsMixins
10
+ from roms_tools.setup.regrid import LateralRegrid
11
11
  from roms_tools.setup.datasets import (
12
12
  ERA5Dataset,
13
13
  ERA5Correction,
@@ -20,6 +20,8 @@ from roms_tools.setup.utils import (
20
20
  get_variable_metadata,
21
21
  group_dataset,
22
22
  save_datasets,
23
+ get_target_coords,
24
+ rotate_velocities,
23
25
  )
24
26
  from roms_tools.setup.plot import _plot
25
27
  import matplotlib.pyplot as plt
@@ -27,7 +29,7 @@ from pathlib import Path
27
29
 
28
30
 
29
31
  @dataclass(frozen=True, kw_only=True)
30
- class SurfaceForcing(ROMSToolsMixins):
32
+ class SurfaceForcing:
31
33
  """Represents surface forcing input data for ROMS.
32
34
 
33
35
  Parameters
@@ -91,69 +93,45 @@ class SurfaceForcing(ROMSToolsMixins):
91
93
  def __post_init__(self):
92
94
 
93
95
  self._input_checks()
94
- lon, lat, angle, straddle = super()._get_target_lon_lat(self.use_coarse_grid)
95
- object.__setattr__(self, "target_lon", lon)
96
- object.__setattr__(self, "target_lat", lat)
96
+ target_coords = get_target_coords(self.grid, self.use_coarse_grid)
97
+ object.__setattr__(self, "target_coords", target_coords)
97
98
 
98
99
  data = self._get_data()
99
100
  data.choose_subdomain(
100
- latitude_range=[lat.min().values, lat.max().values],
101
- longitude_range=[lon.min().values, lon.max().values],
102
- margin=2,
103
- straddle=straddle,
101
+ target_coords,
102
+ buffer_points=20, # lateral fill needs some buffer from data margin
104
103
  )
105
- if self.type == "physics":
106
- vars_2d = ["uwnd", "vwnd", "swrad", "lwrad", "Tair", "qair", "rain"]
107
- elif self.type == "bgc":
108
- vars_2d = data.var_names.keys()
109
- vars_3d = []
110
104
 
111
- data_vars = super()._regrid_data(data, vars_2d, vars_3d, lon, lat)
105
+ data.apply_lateral_fill()
112
106
 
113
- if self.type == "physics":
114
- data_vars = super()._process_velocities(
115
- data_vars, angle, "uwnd", "vwnd", interpolate=False
116
- )
117
- if self.correct_radiation:
118
- correction_data = self._get_correction_data()
119
- # choose same subdomain as forcing data so that we can use same mask
120
- coords_correction = {
121
- correction_data.dim_names["latitude"]: data.ds[
122
- data.dim_names["latitude"]
123
- ],
124
- correction_data.dim_names["longitude"]: data.ds[
125
- data.dim_names["longitude"]
126
- ],
127
- }
128
- correction_data.choose_subdomain(coords_correction, straddle=straddle)
129
- # apply mask from ERA5 data
130
- if "mask" in data.var_names.keys():
131
- mask = data.ds["mask"]
132
- for var in correction_data.ds.data_vars:
133
- correction_data.ds[var] = xr.where(
134
- mask == 1, correction_data.ds[var], np.nan
135
- )
136
- correction_data.ds["mask"] = mask
137
- vars_2d = ["swr_corr"]
138
- vars_3d = []
139
- # spatial interpolation
140
- data_vars_corr = super()._regrid_data(
141
- correction_data, vars_2d, vars_3d, lon, lat
142
- )
143
- # temporal interpolation
144
- corr_factor = interpolate_from_climatology(
145
- data_vars_corr["swr_corr"],
146
- correction_data.dim_names["time"],
147
- time=data_vars["swrad"].time,
107
+ variable_info = self._set_variable_info(data)
108
+ var_names = variable_info.keys()
109
+
110
+ processed_fields = {}
111
+ # lateral regridding
112
+ lateral_regrid = LateralRegrid(target_coords, data.dim_names)
113
+ for var_name in var_names:
114
+ if var_name in data.var_names.keys():
115
+ processed_fields[var_name] = lateral_regrid.apply(
116
+ data.ds[data.var_names[var_name]]
148
117
  )
149
118
 
150
- data_vars["swrad"] = data_vars["swrad"] * corr_factor
119
+ # rotation of velocities and interpolation to u/v points
120
+ if "uwnd" in variable_info and "vwnd" in variable_info:
121
+ processed_fields["uwnd"], processed_fields["vwnd"] = rotate_velocities(
122
+ processed_fields["uwnd"],
123
+ processed_fields["vwnd"],
124
+ target_coords["angle"],
125
+ interpolate=False,
126
+ )
151
127
 
152
- object.__setattr__(data, "data_vars", data_vars)
128
+ # correct radiation
129
+ if self.type == "physics" and self.correct_radiation:
130
+ processed_fields = self._apply_correction(processed_fields, data)
153
131
 
154
132
  d_meta = get_variable_metadata()
155
133
 
156
- ds = self._write_into_dataset(data, d_meta)
134
+ ds = self._write_into_dataset(processed_fields, data, d_meta)
157
135
 
158
136
  if self.use_coarse_grid:
159
137
  mask = self.grid.ds["mask_coarse"].rename(
@@ -162,13 +140,11 @@ class SurfaceForcing(ROMSToolsMixins):
162
140
  else:
163
141
  mask = self.grid.ds["mask_rho"]
164
142
 
165
- # NaN values at wet points indicate that the raw data did not cover the domain, and the following will raise a ValueError
166
- for var in ds.data_vars:
167
- nan_check(ds[var].isel(time=0), mask)
143
+ self._validate(ds, mask)
168
144
 
169
145
  # substitute NaNs over land by a fill value to avoid blow-up of ROMS
170
- for var in ds.data_vars:
171
- ds[var] = substitute_nans_by_fillvalue(ds[var])
146
+ for var_name in ds.data_vars:
147
+ ds[var_name] = substitute_nans_by_fillvalue(ds[var_name])
172
148
 
173
149
  object.__setattr__(self, "ds", ds)
174
150
 
@@ -231,15 +207,98 @@ class SurfaceForcing(ROMSToolsMixins):
231
207
 
232
208
  return correction_data
233
209
 
234
- def _write_into_dataset(self, data, d_meta):
210
+ def _set_variable_info(self, data):
211
+ """Sets up a dictionary with metadata for variables based on the type of data
212
+ (physics or BGC).
213
+
214
+ The dictionary contains the following information:
215
+ - `location`: Where the variable resides in the grid (e.g., rho, u, or v points).
216
+ - `is_vector`: Whether the variable is part of a vector (True for velocity components like 'u' and 'v').
217
+ - `vector_pair`: For vector variables, this indicates the associated variable that forms the vector (e.g., 'u' and 'v').
218
+ - `is_3d`: Indicates whether the variable is 3D (True for variables like 'temp' and 'salt') or 2D (False for 'zeta').
219
+
220
+ Returns
221
+ -------
222
+ dict
223
+ A dictionary where the keys are variable names and the values are dictionaries of metadata
224
+ about each variable, including 'location', 'is_vector', 'vector_pair', and 'is_3d'.
225
+ """
226
+ default_info = {
227
+ "location": "rho",
228
+ "is_vector": False,
229
+ "vector_pair": None,
230
+ "is_3d": False,
231
+ }
232
+
233
+ # Define a dictionary for variable names and their associated information
234
+ if self.type == "physics":
235
+ variable_info = {
236
+ "swrad": default_info,
237
+ "lwrad": default_info,
238
+ "Tair": default_info,
239
+ "qair": default_info,
240
+ "rain": default_info,
241
+ "uwnd": {
242
+ "location": "u",
243
+ "is_vector": True,
244
+ "vector_pair": "vwnd",
245
+ "is_3d": False,
246
+ },
247
+ "vwnd": {
248
+ "location": "v",
249
+ "is_vector": True,
250
+ "vector_pair": "uwnd",
251
+ "is_3d": False,
252
+ },
253
+ }
254
+ elif self.type == "bgc":
255
+ variable_info = {}
256
+ for var in data.var_names.keys():
257
+ variable_info[var] = default_info
258
+
259
+ return variable_info
260
+
261
+ def _apply_correction(self, processed_fields, data):
262
+
263
+ correction_data = self._get_correction_data()
264
+ # choose same subdomain as forcing data so that we can use same mask
265
+ coords_correction = {
266
+ correction_data.dim_names["latitude"]: data.ds[data.dim_names["latitude"]],
267
+ correction_data.dim_names["longitude"]: data.ds[
268
+ data.dim_names["longitude"]
269
+ ],
270
+ }
271
+ correction_data.choose_subdomain(
272
+ coords_correction, straddle=self.target_coords["straddle"]
273
+ )
274
+ correction_data.ds["mask"] = data.ds["mask"] # use mask from ERA5 data
275
+ correction_data.apply_lateral_fill()
276
+ # regrid
277
+ lateral_regrid = LateralRegrid(self.target_coords, correction_data.dim_names)
278
+ corr_factor = lateral_regrid.apply(
279
+ correction_data.ds[correction_data.var_names["swr_corr"]]
280
+ )
281
+
282
+ # temporal interpolation
283
+ corr_factor = interpolate_from_climatology(
284
+ corr_factor,
285
+ correction_data.dim_names["time"],
286
+ time=processed_fields["swrad"].time,
287
+ )
288
+
289
+ processed_fields["swrad"] = processed_fields["swrad"] * corr_factor
290
+
291
+ return processed_fields
292
+
293
+ def _write_into_dataset(self, processed_fields, data, d_meta):
235
294
 
236
295
  # save in new dataset
237
296
  ds = xr.Dataset()
238
297
 
239
- for var in data.data_vars.keys():
240
- ds[var] = data.data_vars[var].astype(np.float32)
241
- ds[var].attrs["long_name"] = d_meta[var]["long_name"]
242
- ds[var].attrs["units"] = d_meta[var]["units"]
298
+ for var_name in processed_fields.keys():
299
+ ds[var_name] = processed_fields[var_name].astype(np.float32)
300
+ ds[var_name].attrs["long_name"] = d_meta[var_name]["long_name"]
301
+ ds[var_name].attrs["units"] = d_meta[var_name]["units"]
243
302
 
244
303
  if self.use_coarse_grid:
245
304
  ds = ds.rename({"eta_coarse": "eta_rho", "xi_coarse": "xi_rho"})
@@ -305,11 +364,36 @@ class SurfaceForcing(ROMSToolsMixins):
305
364
  ds = ds.drop_vars(["time"])
306
365
 
307
366
  variables_to_drop = ["lat_rho", "lon_rho", "lat_coarse", "lon_coarse"]
308
- existing_vars = [var for var in variables_to_drop if var in ds]
367
+ existing_vars = [var_name for var_name in variables_to_drop if var_name in ds]
309
368
  ds = ds.drop_vars(existing_vars)
310
369
 
311
370
  return ds
312
371
 
372
+ def _validate(self, ds, mask):
373
+ """Validates the dataset by checking for NaN values at wet points, which would
374
+ indicate missing raw data coverage over the target domain.
375
+
376
+ Parameters
377
+ ----------
378
+ ds : xarray.Dataset
379
+ The dataset to validate.
380
+ mask : xarray.DataArray
381
+ Land mask (1=ocean, 0=land) to determine wet points in the domain.
382
+
383
+ Raises
384
+ ------
385
+ ValueError
386
+ If NaN values are found in any of the specified variables at wet points,
387
+ indicating incomplete data coverage.
388
+
389
+ Notes
390
+ -----
391
+ This check is applied to the first time step (`time=0`) of each variable in the provided dataset.
392
+ """
393
+
394
+ for var_name in ds.data_vars:
395
+ nan_check(ds[var_name].isel(time=0), mask)
396
+
313
397
  def _add_global_metadata(self, ds=None):
314
398
 
315
399
  if ds is None:
@@ -333,12 +417,12 @@ class SurfaceForcing(ROMSToolsMixins):
333
417
 
334
418
  return ds
335
419
 
336
- def plot(self, varname, time=0) -> None:
420
+ def plot(self, var_name, time=0) -> None:
337
421
  """Plot the specified surface forcing field for a given time slice.
338
422
 
339
423
  Parameters
340
424
  ----------
341
- varname : str
425
+ var_name : str
342
426
  The name of the surface forcing field to plot. Options include:
343
427
 
344
428
  - "uwnd": 10 meter wind in x-direction.
@@ -367,7 +451,7 @@ class SurfaceForcing(ROMSToolsMixins):
367
451
  Raises
368
452
  ------
369
453
  ValueError
370
- If the specified varname is not found in dataset.
454
+ If the specified var_name is not found in dataset.
371
455
 
372
456
 
373
457
  Examples
@@ -375,10 +459,10 @@ class SurfaceForcing(ROMSToolsMixins):
375
459
  >>> atm_forcing.plot("uwnd", time=0)
376
460
  """
377
461
 
378
- if varname not in self.ds:
379
- raise ValueError(f"Variable '{varname}' is not found in dataset.")
462
+ if var_name not in self.ds:
463
+ raise ValueError(f"Variable '{var_name}' is not found in dataset.")
380
464
 
381
- field = self.ds[varname].isel(time=time).load()
465
+ field = self.ds[var_name].isel(time=time).load()
382
466
  title = field.long_name
383
467
 
384
468
  # assign lat / lon
@@ -388,17 +472,19 @@ class SurfaceForcing(ROMSToolsMixins):
388
472
  else:
389
473
  field = field.where(self.grid.ds.mask_rho)
390
474
 
391
- field = field.assign_coords({"lon": self.target_lon, "lat": self.target_lat})
475
+ field = field.assign_coords(
476
+ {"lon": self.target_coords["lon"], "lat": self.target_coords["lat"]}
477
+ )
392
478
 
393
479
  # choose colorbar
394
- if varname in ["uwnd", "vwnd"]:
480
+ if var_name in ["uwnd", "vwnd"]:
395
481
  vmax = max(field.max().values, -field.min().values)
396
482
  vmin = -vmax
397
483
  cmap = plt.colormaps.get_cmap("RdBu_r")
398
484
  else:
399
485
  vmax = field.max().values
400
486
  vmin = field.min().values
401
- if varname in ["swrad", "lwrad", "Tair", "qair"]:
487
+ if var_name in ["swrad", "lwrad", "Tair", "qair"]:
402
488
  cmap = plt.colormaps.get_cmap("YlOrRd")
403
489
  else:
404
490
  cmap = plt.colormaps.get_cmap("YlGnBu")
roms_tools/setup/tides.py CHANGED
@@ -16,15 +16,18 @@ from roms_tools.setup.utils import (
16
16
  interpolate_from_rho_to_v,
17
17
  get_variable_metadata,
18
18
  save_datasets,
19
+ get_target_coords,
20
+ rotate_velocities,
21
+ get_vector_pairs,
19
22
  )
20
- from roms_tools.setup.mixins import ROMSToolsMixins
23
+ from roms_tools.setup.regrid import LateralRegrid
21
24
  import matplotlib.pyplot as plt
22
25
  from pathlib import Path
23
26
 
24
27
 
25
28
  @dataclass(frozen=True, kw_only=True)
26
- class TidalForcing(ROMSToolsMixins):
27
- """Represents tidal forcing data used in ocean modeling.
29
+ class TidalForcing:
30
+ """Represents tidal forcing for ROMS.
28
31
 
29
32
  Parameters
30
33
  ----------
@@ -68,67 +71,69 @@ class TidalForcing(ROMSToolsMixins):
68
71
  def __post_init__(self):
69
72
 
70
73
  self._input_checks()
71
- lon, lat, angle, straddle = super()._get_target_lon_lat()
74
+ target_coords = get_target_coords(self.grid)
72
75
 
73
76
  data = self._get_data()
74
-
75
77
  data.check_number_constituents(self.ntides)
76
78
  data.choose_subdomain(
77
- latitude_range=[lat.min().values, lat.max().values],
78
- longitude_range=[lon.min().values, lon.max().values],
79
- margin=2,
80
- straddle=straddle,
79
+ target_coords,
80
+ buffer_points=20,
81
81
  )
82
-
83
82
  # select desired number of constituents
84
83
  object.__setattr__(data, "ds", data.ds.isel(ntides=slice(None, self.ntides)))
85
-
86
84
  self._correct_tides(data)
87
85
 
88
- vars_2d = [
89
- "ssh_Re",
90
- "ssh_Im",
91
- "pot_Re",
92
- "pot_Im",
93
- "u_Re",
94
- "u_Im",
95
- "v_Re",
96
- "v_Im",
97
- ]
98
- vars_3d = []
99
-
100
- data_vars = super()._regrid_data(data, vars_2d, vars_3d, lon, lat)
101
-
102
- data_vars = super()._process_velocities(
103
- data_vars, angle, "u_Re", "v_Re", interpolate=False
104
- )
105
- data_vars = super()._process_velocities(
106
- data_vars, angle, "u_Im", "v_Im", interpolate=False
107
- )
108
-
109
- # Convert to barotropic velocity
110
- for varname in ["u_Re", "v_Re", "u_Im", "v_Im"]:
111
- data_vars[varname] = data_vars[varname] / self.grid.ds.h
112
-
113
- # Interpolate from rho- to velocity points
86
+ data.apply_lateral_fill()
87
+
88
+ variable_info = self._set_variable_info()
89
+ var_names = variable_info.keys()
90
+
91
+ processed_fields = {}
92
+ # lateral regridding
93
+ lateral_regrid = LateralRegrid(target_coords, data.dim_names)
94
+ for var_name in var_names:
95
+ if var_name in data.var_names.keys():
96
+ processed_fields[var_name] = lateral_regrid.apply(
97
+ data.ds[data.var_names[var_name]]
98
+ )
99
+
100
+ # rotation of velocities and interpolation to u/v points
101
+ vector_pairs = get_vector_pairs(variable_info)
102
+ for pair in vector_pairs:
103
+ u_component = pair[0]
104
+ v_component = pair[1]
105
+ if u_component in processed_fields and v_component in processed_fields:
106
+ (
107
+ processed_fields[u_component],
108
+ processed_fields[v_component],
109
+ ) = rotate_velocities(
110
+ processed_fields[u_component],
111
+ processed_fields[v_component],
112
+ target_coords["angle"],
113
+ interpolate=False,
114
+ )
115
+
116
+ # convert to barotropic velocity
117
+ for var_name in ["u_Re", "v_Re", "u_Im", "v_Im"]:
118
+ processed_fields[var_name] = processed_fields[var_name] / self.grid.ds.h
119
+
120
+ # interpolate from rho- to velocity points
114
121
  for uname in ["u_Re", "u_Im"]:
115
- data_vars[uname] = interpolate_from_rho_to_u(data_vars[uname])
122
+ processed_fields[uname] = interpolate_from_rho_to_u(processed_fields[uname])
116
123
  for vname in ["v_Re", "v_Im"]:
117
- data_vars[vname] = interpolate_from_rho_to_v(data_vars[vname])
124
+ processed_fields[vname] = interpolate_from_rho_to_v(processed_fields[vname])
118
125
 
119
126
  d_meta = get_variable_metadata()
120
- ds = self._write_into_dataset(data_vars, d_meta)
127
+ ds = self._write_into_dataset(processed_fields, d_meta)
121
128
  ds["omega"] = data.ds["omega"]
122
129
 
123
130
  ds = self._add_global_metadata(ds)
124
131
 
125
- # NaN values at wet points indicate that the raw data did not cover the domain, and the following will raise a ValueError
126
- for var in ["ssh_Re", "u_Re", "v_Im"]:
127
- nan_check(ds[var].isel(ntides=0), self.grid.ds.mask_rho)
132
+ self._validate(ds)
128
133
 
129
134
  # substitute NaNs over land by a fill value to avoid blow-up of ROMS
130
- for var in ds.data_vars:
131
- ds[var] = substitute_nans_by_fillvalue(ds[var])
135
+ for var_name in ds.data_vars:
136
+ ds[var_name] = substitute_nans_by_fillvalue(ds[var_name])
132
137
 
133
138
  object.__setattr__(self, "ds", ds)
134
139
 
@@ -147,15 +152,71 @@ class TidalForcing(ROMSToolsMixins):
147
152
  raise ValueError('Only "TPXO" is a valid option for source["name"].')
148
153
  return data
149
154
 
150
- def _write_into_dataset(self, data_vars, d_meta):
155
+ def _set_variable_info(self):
156
+ """Sets up a dictionary with metadata for variables based on the type.
157
+
158
+ The dictionary contains the following information:
159
+ - `location`: Where the variable resides in the grid (e.g., rho, u, or v points).
160
+ - `is_vector`: Whether the variable is part of a vector (True for velocity components like 'u' and 'v').
161
+ - `vector_pair`: For vector variables, this indicates the associated variable that forms the vector (e.g., 'u' and 'v').
162
+ - `is_3d`: Indicates whether the variable is 3D (True for variables like 'temp' and 'salt') or 2D (False for 'zeta').
163
+
164
+ Returns
165
+ -------
166
+ dict
167
+ A dictionary where the keys are variable names and the values are dictionaries of metadata
168
+ about each variable, including 'location', 'is_vector', 'vector_pair', and 'is_3d'.
169
+ """
170
+ default_info = {
171
+ "location": "rho",
172
+ "is_vector": False,
173
+ "vector_pair": None,
174
+ "is_3d": False,
175
+ }
176
+
177
+ # Define a dictionary for variable names and their associated information
178
+ variable_info = {
179
+ "ssh_Re": default_info,
180
+ "ssh_Im": default_info,
181
+ "pot_Re": default_info,
182
+ "pot_Im": default_info,
183
+ "u_Re": {
184
+ "location": "u",
185
+ "is_vector": True,
186
+ "vector_pair": "v_Re",
187
+ "is_3d": False,
188
+ },
189
+ "v_Re": {
190
+ "location": "v",
191
+ "is_vector": True,
192
+ "vector_pair": "u_Re",
193
+ "is_3d": False,
194
+ },
195
+ "u_Im": {
196
+ "location": "u",
197
+ "is_vector": True,
198
+ "vector_pair": "v_Im",
199
+ "is_3d": False,
200
+ },
201
+ "v_Im": {
202
+ "location": "v",
203
+ "is_vector": True,
204
+ "vector_pair": "u_Im",
205
+ "is_3d": False,
206
+ },
207
+ }
208
+
209
+ return variable_info
210
+
211
+ def _write_into_dataset(self, processed_fields, d_meta):
151
212
 
152
213
  # save in new dataset
153
214
  ds = xr.Dataset()
154
215
 
155
- for var in data_vars.keys():
156
- ds[var] = data_vars[var].astype(np.float32)
157
- ds[var].attrs["long_name"] = d_meta[var]["long_name"]
158
- ds[var].attrs["units"] = d_meta[var]["units"]
216
+ for var_name in processed_fields.keys():
217
+ ds[var_name] = processed_fields[var_name].astype(np.float32)
218
+ ds[var_name].attrs["long_name"] = d_meta[var_name]["long_name"]
219
+ ds[var_name].attrs["units"] = d_meta[var_name]["units"]
159
220
 
160
221
  ds = ds.drop_vars(["lat_rho", "lon_rho"])
161
222
 
@@ -178,12 +239,35 @@ class TidalForcing(ROMSToolsMixins):
178
239
 
179
240
  return ds
180
241
 
181
- def plot(self, varname, ntides=0) -> None:
242
+ def _validate(self, ds):
243
+ """Validates the dataset by checking for NaN values at wet points, which would
244
+ indicate missing raw data coverage over the target domain.
245
+
246
+ Parameters
247
+ ----------
248
+ ds : xarray.Dataset
249
+ The dataset to validate, containing tidal variables and a mask for wet points.
250
+
251
+ Raises
252
+ ------
253
+ ValueError
254
+ If NaN values are found in any of the specified variables at wet points,
255
+ indicating incomplete data coverage.
256
+
257
+ Notes
258
+ -----
259
+ This check is applied to the first constituent (`ntides=0`) of each variable in the dataset.
260
+ The method utilizes `self.grid.ds.mask_rho` to determine the wet points in the domain.
261
+ """
262
+ for var_name in ds.data_vars:
263
+ nan_check(ds[var_name].isel(ntides=0), self.grid.ds.mask_rho)
264
+
265
+ def plot(self, var_name, ntides=0) -> None:
182
266
  """Plot the specified tidal forcing variable for a given tidal constituent.
183
267
 
184
268
  Parameters
185
269
  ----------
186
- varname : str
270
+ var_name : str
187
271
  The tidal forcing variable to plot. Options include:
188
272
 
189
273
  - "ssh_Re": Real part of tidal elevation.
@@ -216,7 +300,7 @@ class TidalForcing(ROMSToolsMixins):
216
300
  >>> tidal_forcing.plot("ssh_Re", nc=0)
217
301
  """
218
302
 
219
- field = self.ds[varname].isel(ntides=ntides).compute()
303
+ field = self.ds[var_name].isel(ntides=ntides).compute()
220
304
  if all(dim in field.dims for dim in ["eta_rho", "xi_rho"]):
221
305
  field = field.where(self.grid.ds.mask_rho)
222
306
  field = field.assign_coords(
@@ -237,7 +321,7 @@ class TidalForcing(ROMSToolsMixins):
237
321
  else:
238
322
  ValueError("provided field does not have two horizontal dimension")
239
323
 
240
- title = "%s, ntides = %i" % (field.long_name, self.ds[varname].ntides[ntides])
324
+ title = "%s, ntides = %i" % (field.long_name, self.ds[var_name].ntides[ntides])
241
325
 
242
326
  vmax = max(field.max(), -field.min())
243
327
  vmin = -vmax
@@ -457,6 +541,9 @@ class TidalForcing(ROMSToolsMixins):
457
541
 
458
542
  # Update var_names dictionary
459
543
  var_names = {**data.var_names, "pot_Re": "pot_Re", "pot_Im": "pot_Im"}
544
+ var_names.pop("sal_Re", None) # Remove "sal_Re" if it exists
545
+ var_names.pop("sal_Im", None) # Remove "sal_Im" if it exists
546
+
460
547
  object.__setattr__(data, "var_names", var_names)
461
548
 
462
549