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
@@ -12,15 +12,19 @@ from roms_tools.setup.utils import (
12
12
  substitute_nans_by_fillvalue,
13
13
  get_variable_metadata,
14
14
  save_datasets,
15
+ get_target_coords,
16
+ rotate_velocities,
17
+ compute_barotropic_velocity,
18
+ transpose_dimensions,
15
19
  )
16
- from roms_tools.setup.mixins import ROMSToolsMixins
20
+ from roms_tools.setup.regrid import LateralRegrid, VerticalRegrid
17
21
  from roms_tools.setup.plot import _plot, _section_plot, _profile_plot, _line_plot
18
22
  import matplotlib.pyplot as plt
19
23
  from pathlib import Path
20
24
 
21
25
 
22
26
  @dataclass(frozen=True, kw_only=True)
23
- class InitialConditions(ROMSToolsMixins):
27
+ class InitialConditions:
24
28
  """Represents initial conditions for ROMS, including physical and biogeochemical
25
29
  data.
26
30
 
@@ -85,58 +89,103 @@ class InitialConditions(ROMSToolsMixins):
85
89
  def __post_init__(self):
86
90
 
87
91
  self._input_checks()
88
- lon, lat, angle, straddle = super()._get_target_lon_lat()
89
92
 
90
- data = self._get_data()
91
- data.choose_subdomain(
92
- latitude_range=[lat.min().values, lat.max().values],
93
- longitude_range=[lon.min().values, lon.max().values],
94
- margin=2,
95
- straddle=straddle,
96
- )
97
-
98
- vars_2d = ["zeta"]
99
- vars_3d = ["temp", "salt", "u", "v"]
100
- data_vars = super()._regrid_data(data, vars_2d, vars_3d, lon, lat)
101
- data_vars = super()._process_velocities(data_vars, angle, "u", "v")
93
+ processed_fields = {}
94
+ processed_fields = self._process_data(processed_fields, type="physics")
102
95
 
103
96
  if self.bgc_source is not None:
104
- bgc_data = self._get_bgc_data()
105
- bgc_data.choose_subdomain(
106
- latitude_range=[lat.min().values, lat.max().values],
107
- longitude_range=[lon.min().values, lon.max().values],
108
- margin=2,
109
- straddle=straddle,
110
- )
111
-
112
- vars_2d = []
113
- vars_3d = bgc_data.var_names.keys()
114
- bgc_data_vars = super()._regrid_data(bgc_data, vars_2d, vars_3d, lon, lat)
97
+ processed_fields = self._process_data(processed_fields, type="bgc")
115
98
 
116
- # Ensure time coordinate matches that of physical variables
117
- for var in bgc_data_vars.keys():
118
- bgc_data_vars[var] = bgc_data_vars[var].assign_coords(
119
- {"time": data_vars["temp"]["time"]}
120
- )
121
-
122
- # Combine data variables from physical and biogeochemical sources
123
- data_vars.update(bgc_data_vars)
99
+ for var_name in processed_fields.keys():
100
+ processed_fields[var_name] = transpose_dimensions(
101
+ processed_fields[var_name]
102
+ )
124
103
 
125
104
  d_meta = get_variable_metadata()
126
- ds = self._write_into_dataset(data_vars, d_meta)
105
+ ds = self._write_into_dataset(processed_fields, d_meta)
127
106
 
128
107
  ds = self._add_global_metadata(ds)
129
108
 
130
- ds["zeta"].load()
131
- # NaN values at wet points indicate that the raw data did not cover the domain, and the following will raise a ValueError
132
- nan_check(ds["zeta"].squeeze(), self.grid.ds.mask_rho)
109
+ self._validate(ds)
133
110
 
134
111
  # substitute NaNs over land by a fill value to avoid blow-up of ROMS
135
- for var in ds.data_vars:
136
- ds[var] = substitute_nans_by_fillvalue(ds[var])
112
+ for var_name in ds.data_vars:
113
+ ds[var_name] = substitute_nans_by_fillvalue(ds[var_name])
137
114
 
138
115
  object.__setattr__(self, "ds", ds)
139
116
 
117
+ def _process_data(self, processed_fields, type="physics"):
118
+
119
+ target_coords = get_target_coords(self.grid)
120
+
121
+ if type == "physics":
122
+ data = self._get_data()
123
+ else:
124
+ data = self._get_bgc_data()
125
+
126
+ data.choose_subdomain(
127
+ target_coords,
128
+ buffer_points=20, # lateral fill needs good buffer from data margin
129
+ )
130
+
131
+ data.extrapolate_deepest_to_bottom()
132
+ data.apply_lateral_fill()
133
+
134
+ variable_info = self._set_variable_info(data, type=type)
135
+ var_names = variable_info.keys()
136
+
137
+ # lateral regridding
138
+ lateral_regrid = LateralRegrid(target_coords, data.dim_names)
139
+ for var_name in var_names:
140
+ if var_name in data.var_names.keys():
141
+ processed_fields[var_name] = lateral_regrid.apply(
142
+ data.ds[data.var_names[var_name]]
143
+ )
144
+
145
+ # rotation of velocities and interpolation to u/v points
146
+ if "u" in variable_info and "v" in variable_info:
147
+ (processed_fields["u"], processed_fields["v"],) = rotate_velocities(
148
+ processed_fields["u"],
149
+ processed_fields["v"],
150
+ target_coords["angle"],
151
+ interpolate=True,
152
+ )
153
+
154
+ # vertical regridding
155
+ for location in ["rho", "u", "v"]:
156
+ var_names = [
157
+ name
158
+ for name, info in variable_info.items()
159
+ if info["location"] == location and info["is_3d"]
160
+ ]
161
+ if len(var_names) > 0:
162
+ vertical_regrid = VerticalRegrid(
163
+ self.grid.ds[f"layer_depth_{location}"],
164
+ data.ds[data.dim_names["depth"]],
165
+ )
166
+ for var_name in var_names:
167
+ if var_name in processed_fields:
168
+ processed_fields[var_name] = vertical_regrid.apply(
169
+ processed_fields[var_name]
170
+ )
171
+
172
+ # compute barotropic velocities
173
+ if "u" in variable_info and "v" in variable_info:
174
+ for var_name in ["u", "v"]:
175
+ processed_fields[f"{var_name}bar"] = compute_barotropic_velocity(
176
+ processed_fields[var_name],
177
+ self.grid.ds[f"interface_depth_{var_name}"],
178
+ )
179
+
180
+ if type == "bgc":
181
+ # Ensure time coordinate matches that of physical variables
182
+ for var_name in variable_info.keys():
183
+ processed_fields[var_name] = processed_fields[var_name].assign_coords(
184
+ {"time": processed_fields["temp"]["time"]}
185
+ )
186
+
187
+ return processed_fields
188
+
140
189
  def _input_checks(self):
141
190
 
142
191
  if "name" not in self.source.keys():
@@ -201,19 +250,86 @@ class InitialConditions(ROMSToolsMixins):
201
250
 
202
251
  return data
203
252
 
204
- def _write_into_dataset(self, data_vars, d_meta):
253
+ def _set_variable_info(self, data, type="physics"):
254
+ """Sets up a dictionary with metadata for variables based on the type.
255
+
256
+ The dictionary contains the following information:
257
+ - `location`: Where the variable resides in the grid (e.g., rho, u, or v points).
258
+ - `is_vector`: Whether the variable is part of a vector (True for velocity components like 'u' and 'v').
259
+ - `vector_pair`: For vector variables, this indicates the associated variable that forms the vector (e.g., 'u' and 'v').
260
+ - `is_3d`: Indicates whether the variable is 3D (True for variables like 'temp' and 'salt') or 2D (False for 'zeta').
261
+
262
+ Returns
263
+ -------
264
+ dict
265
+ A dictionary where the keys are variable names and the values are dictionaries of metadata
266
+ about each variable, including 'location', 'is_vector', 'vector_pair', and 'is_3d'.
267
+ """
268
+ default_info = {
269
+ "location": "rho",
270
+ "is_vector": False,
271
+ "vector_pair": None,
272
+ "is_3d": True,
273
+ }
274
+
275
+ # Define a dictionary for variable names and their associated information
276
+ if type == "physics":
277
+ variable_info = {
278
+ "zeta": {
279
+ "location": "rho",
280
+ "is_vector": False,
281
+ "vector_pair": None,
282
+ "is_3d": False,
283
+ },
284
+ "temp": default_info,
285
+ "salt": default_info,
286
+ "u": {
287
+ "location": "u",
288
+ "is_vector": True,
289
+ "vector_pair": "v",
290
+ "is_3d": True,
291
+ },
292
+ "v": {
293
+ "location": "v",
294
+ "is_vector": True,
295
+ "vector_pair": "u",
296
+ "is_3d": True,
297
+ },
298
+ "ubar": {
299
+ "location": "u",
300
+ "is_vector": True,
301
+ "vector_pair": "vbar",
302
+ "is_3d": False,
303
+ },
304
+ "vbar": {
305
+ "location": "v",
306
+ "is_vector": True,
307
+ "vector_pair": "ubar",
308
+ "is_3d": False,
309
+ },
310
+ }
311
+ elif type == "bgc":
312
+ variable_info = {}
313
+ for var_name in data.var_names.keys():
314
+ variable_info[var_name] = default_info
315
+
316
+ return variable_info
317
+
318
+ def _write_into_dataset(self, processed_fields, d_meta):
205
319
 
206
320
  # save in new dataset
207
321
  ds = xr.Dataset()
208
322
 
209
- for var in data_vars.keys():
210
- ds[var] = data_vars[var].astype(np.float32)
211
- ds[var].attrs["long_name"] = d_meta[var]["long_name"]
212
- ds[var].attrs["units"] = d_meta[var]["units"]
323
+ for var_name in processed_fields.keys():
324
+ ds[var_name] = processed_fields[var_name].astype(np.float32)
325
+ ds[var_name].attrs["long_name"] = d_meta[var_name]["long_name"]
326
+ ds[var_name].attrs["units"] = d_meta[var_name]["units"]
213
327
 
214
328
  # initialize vertical velocity to zero
215
329
  ds["w"] = xr.zeros_like(
216
- self.grid.ds["interface_depth_rho"].expand_dims(time=data_vars["u"].time)
330
+ self.grid.ds["interface_depth_rho"].expand_dims(
331
+ time=processed_fields["u"].time
332
+ )
217
333
  ).astype(np.float32)
218
334
  ds["w"].attrs["long_name"] = d_meta["w"]["long_name"]
219
335
  ds["w"].attrs["units"] = d_meta["w"]["units"]
@@ -222,14 +338,18 @@ class InitialConditions(ROMSToolsMixins):
222
338
  "s_rho",
223
339
  "lat_rho",
224
340
  "lon_rho",
225
- "layer_depth_rho",
226
- "interface_depth_rho",
227
341
  "lat_u",
228
342
  "lon_u",
229
343
  "lat_v",
230
344
  "lon_v",
345
+ "layer_depth_rho",
346
+ "interface_depth_rho",
347
+ "layer_depth_u",
348
+ "interface_depth_u",
349
+ "layer_depth_v",
350
+ "interface_depth_v",
231
351
  ]
232
- existing_vars = [var for var in variables_to_drop if var in ds]
352
+ existing_vars = [var_name for var_name in variables_to_drop if var_name in ds]
233
353
  ds = ds.drop_vars(existing_vars)
234
354
 
235
355
  ds["Cs_r"] = self.grid.ds["Cs_r"]
@@ -253,6 +373,29 @@ class InitialConditions(ROMSToolsMixins):
253
373
 
254
374
  return ds
255
375
 
376
+ def _validate(self, ds):
377
+ """Validates the dataset by checking for NaN values in SSH at wet points, which
378
+ would indicate missing raw data coverage over the target domain.
379
+
380
+ Parameters
381
+ ----------
382
+ ds : xarray.Dataset
383
+ The dataset to validate.
384
+
385
+ Raises
386
+ ------
387
+ ValueError
388
+ If NaN values are found in any of the specified variables at wet points,
389
+ indicating incomplete data coverage.
390
+
391
+ Notes
392
+ -----
393
+ This check is only applied to the 2D variable SSH to improve performance.
394
+ """
395
+
396
+ ds["zeta"].load()
397
+ nan_check(ds["zeta"].squeeze(), self.grid.ds.mask_rho)
398
+
256
399
  def _add_global_metadata(self, ds):
257
400
 
258
401
  ds.attrs["title"] = "ROMS initial conditions file created by ROMS-Tools"
@@ -276,7 +419,7 @@ class InitialConditions(ROMSToolsMixins):
276
419
 
277
420
  def plot(
278
421
  self,
279
- varname,
422
+ var_name,
280
423
  s=None,
281
424
  eta=None,
282
425
  xi=None,
@@ -287,7 +430,7 @@ class InitialConditions(ROMSToolsMixins):
287
430
 
288
431
  Parameters
289
432
  ----------
290
- varname : str
433
+ var_name : str
291
434
  The name of the initial conditions field to plot. Options include:
292
435
 
293
436
  - "temp": Potential temperature.
@@ -358,30 +501,30 @@ class InitialConditions(ROMSToolsMixins):
358
501
  Raises
359
502
  ------
360
503
  ValueError
361
- If the specified `varname` is not one of the valid options.
362
- If the field specified by `varname` is 3D and none of `s`, `eta`, or `xi` are specified.
363
- If the field specified by `varname` is 2D and both `eta` and `xi` are specified.
504
+ If the specified `var_name` is not one of the valid options.
505
+ If the field specified by `var_name` is 3D and none of `s`, `eta`, or `xi` are specified.
506
+ If the field specified by `var_name` is 2D and both `eta` and `xi` are specified.
364
507
  """
365
508
 
366
- if len(self.ds[varname].squeeze().dims) == 3 and not any(
509
+ if len(self.ds[var_name].squeeze().dims) == 3 and not any(
367
510
  [s is not None, eta is not None, xi is not None]
368
511
  ):
369
512
  raise ValueError(
370
513
  "For 3D fields, at least one of s, eta, or xi must be specified."
371
514
  )
372
515
 
373
- if len(self.ds[varname].squeeze().dims) == 2 and all(
516
+ if len(self.ds[var_name].squeeze().dims) == 2 and all(
374
517
  [eta is not None, xi is not None]
375
518
  ):
376
519
  raise ValueError("For 2D fields, specify either eta or xi, not both.")
377
520
 
378
- self.ds[varname].load()
379
- field = self.ds[varname].squeeze()
521
+ self.ds[var_name].load()
522
+ field = self.ds[var_name].squeeze()
380
523
 
381
524
  if all(dim in field.dims for dim in ["eta_rho", "xi_rho"]):
382
525
  interface_depth = self.grid.ds.interface_depth_rho
383
526
  layer_depth = self.grid.ds.layer_depth_rho
384
- field = field.where(self.grid.ds.mask_rho)
527
+ mask = self.grid.ds.mask_rho
385
528
  field = field.assign_coords(
386
529
  {"lon": self.grid.ds.lon_rho, "lat": self.grid.ds.lat_rho}
387
530
  )
@@ -389,7 +532,7 @@ class InitialConditions(ROMSToolsMixins):
389
532
  elif all(dim in field.dims for dim in ["eta_rho", "xi_u"]):
390
533
  interface_depth = self.grid.ds.interface_depth_u
391
534
  layer_depth = self.grid.ds.layer_depth_u
392
- field = field.where(self.grid.ds.mask_u)
535
+ mask = self.grid.ds.mask_u
393
536
  field = field.assign_coords(
394
537
  {"lon": self.grid.ds.lon_u, "lat": self.grid.ds.lat_u}
395
538
  )
@@ -397,7 +540,7 @@ class InitialConditions(ROMSToolsMixins):
397
540
  elif all(dim in field.dims for dim in ["eta_v", "xi_rho"]):
398
541
  interface_depth = self.grid.ds.interface_depth_v
399
542
  layer_depth = self.grid.ds.layer_depth_v
400
- field = field.where(self.grid.ds.mask_v)
543
+ mask = self.grid.ds.mask_v
401
544
  field = field.assign_coords(
402
545
  {"lon": self.grid.ds.lon_v, "lat": self.grid.ds.lat_v}
403
546
  )
@@ -419,45 +562,49 @@ class InitialConditions(ROMSToolsMixins):
419
562
  title = title + f", eta_rho = {field.eta_rho[eta].item()}"
420
563
  field = field.isel(eta_rho=eta)
421
564
  layer_depth = layer_depth.isel(eta_rho=eta)
422
- field = field.assign_coords({"layer_depth": layer_depth})
423
565
  interface_depth = interface_depth.isel(eta_rho=eta)
566
+ if "s_rho" in field.dims:
567
+ field = field.assign_coords({"layer_depth": layer_depth})
424
568
  elif "eta_v" in field.dims:
425
569
  title = title + f", eta_v = {field.eta_v[eta].item()}"
426
570
  field = field.isel(eta_v=eta)
427
571
  layer_depth = layer_depth.isel(eta_v=eta)
428
- field = field.assign_coords({"layer_depth": layer_depth})
429
572
  interface_depth = interface_depth.isel(eta_v=eta)
573
+ if "s_rho" in field.dims:
574
+ field = field.assign_coords({"layer_depth": layer_depth})
430
575
  else:
431
576
  raise ValueError(
432
- f"None of the expected dimensions (eta_rho, eta_v) found in ds[{varname}]."
577
+ f"None of the expected dimensions (eta_rho, eta_v) found in ds[{var_name}]."
433
578
  )
434
579
  if xi is not None:
435
580
  if "xi_rho" in field.dims:
436
581
  title = title + f", xi_rho = {field.xi_rho[xi].item()}"
437
582
  field = field.isel(xi_rho=xi)
438
583
  layer_depth = layer_depth.isel(xi_rho=xi)
439
- field = field.assign_coords({"layer_depth": layer_depth})
440
584
  interface_depth = interface_depth.isel(xi_rho=xi)
585
+ if "s_rho" in field.dims:
586
+ field = field.assign_coords({"layer_depth": layer_depth})
441
587
  elif "xi_u" in field.dims:
442
588
  title = title + f", xi_u = {field.xi_u[xi].item()}"
443
589
  field = field.isel(xi_u=xi)
444
590
  layer_depth = layer_depth.isel(xi_u=xi)
445
- field = field.assign_coords({"layer_depth": layer_depth})
446
591
  interface_depth = interface_depth.isel(xi_u=xi)
592
+ if "s_rho" in field.dims:
593
+ field = field.assign_coords({"layer_depth": layer_depth})
447
594
  else:
448
595
  raise ValueError(
449
- f"None of the expected dimensions (xi_rho, xi_u) found in ds[{varname}]."
596
+ f"None of the expected dimensions (xi_rho, xi_u) found in ds[{var_name}]."
450
597
  )
451
598
 
452
599
  # chose colorbar
453
- if varname in ["u", "v", "w", "ubar", "vbar", "zeta"]:
600
+ if var_name in ["u", "v", "w", "ubar", "vbar", "zeta"]:
454
601
  vmax = max(field.max().values, -field.min().values)
455
602
  vmin = -vmax
456
603
  cmap = plt.colormaps.get_cmap("RdBu_r")
457
604
  else:
458
605
  vmax = field.max().values
459
606
  vmin = field.min().values
460
- if varname in ["temp", "salt"]:
607
+ if var_name in ["temp", "salt"]:
461
608
  cmap = plt.colormaps.get_cmap("YlOrRd")
462
609
  else:
463
610
  cmap = plt.colormaps.get_cmap("YlGn")
@@ -467,7 +614,7 @@ class InitialConditions(ROMSToolsMixins):
467
614
  if eta is None and xi is None:
468
615
  _plot(
469
616
  self.grid.ds,
470
- field=field,
617
+ field=field.where(mask),
471
618
  straddle=self.grid.straddle,
472
619
  depth_contours=depth_contours,
473
620
  title=title,
@@ -0,0 +1,143 @@
1
+ import xarray as xr
2
+
3
+
4
+ class LateralRegrid:
5
+ """Handles lateral regridding of data onto a new spatial grid."""
6
+
7
+ def __init__(self, target_coords, source_dim_names):
8
+ """Initialize target grid coordinates and names for grid dimensions.
9
+
10
+ Parameters
11
+ ----------
12
+ target_coords : dict
13
+ Dictionary containing 'lon' and 'lat' as xarray.DataArrays representing
14
+ the longitude and latitude values of the target grid.
15
+ source_dim_names : dict
16
+ Dictionary specifying names for the latitude and longitude dimensions,
17
+ typically using keys like "latitude" and "longitude" to align with the dataset conventions.
18
+
19
+ Attributes
20
+ ----------
21
+ coords : dict
22
+ Maps the dimension names to the corresponding latitude and longitude
23
+ DataArrays, providing easy access to target grid coordinates.
24
+ """
25
+
26
+ self.coords = {
27
+ source_dim_names["latitude"]: target_coords["lat"],
28
+ source_dim_names["longitude"]: target_coords["lon"],
29
+ }
30
+
31
+ def apply(self, da):
32
+ """Fills missing values and regrids the variable.
33
+
34
+ Parameters
35
+ ----------
36
+ da : xarray.DataArray
37
+ Input data to fill and regrid.
38
+
39
+ Returns
40
+ -------
41
+ xarray.DataArray
42
+ Regridded data with filled values.
43
+ """
44
+ regridded = da.interp(self.coords, method="linear").drop_vars(
45
+ list(self.coords.keys())
46
+ )
47
+ return regridded
48
+
49
+
50
+ class VerticalRegrid:
51
+ """Interpolates data onto new vertical (depth) coordinates.
52
+
53
+ Parameters
54
+ ----------
55
+ target_depth_coords : xarray.DataArray
56
+ Depth coordinates for the target grid.
57
+ source_depth_coords : xarray.DataArray
58
+ Depth coordinates for the source grid.
59
+ """
60
+
61
+ def __init__(self, target_depth_coords, source_depth_coords):
62
+ """Initialize regridding factors for interpolation.
63
+
64
+ Parameters
65
+ ----------
66
+ target_depth_coords : xarray.DataArray
67
+ Depth coordinates for the target grid.
68
+ source_depth_coords : xarray.DataArray
69
+ Depth coordinates for the source grid.
70
+
71
+ Attributes
72
+ ----------
73
+ coeff : xarray.Dataset
74
+ Dataset containing:
75
+ - `is_below` : Boolean mask for depths just below target.
76
+ - `is_above` : Boolean mask for depths just above target.
77
+ - `upper_mask`, `lower_mask` : Masks for valid interpolation bounds.
78
+ - `factor` : Weight for blending values between levels.
79
+ """
80
+
81
+ self.depth_dim = source_depth_coords.dims[0]
82
+ source_depth = source_depth_coords
83
+ dims = {"dim": self.depth_dim}
84
+
85
+ dlev = source_depth - target_depth_coords
86
+ is_below = dlev == dlev.where(dlev >= 0).min(**dims)
87
+ is_above = dlev == dlev.where(dlev <= 0).max(**dims)
88
+ p_below = dlev.where(is_below).sum(**dims)
89
+ p_above = -dlev.where(is_above).sum(**dims)
90
+ denominator = p_below + p_above
91
+ denominator = denominator.where(denominator > 1e-6, 1e-6)
92
+ factor = p_below / denominator
93
+
94
+ upper_mask = is_above.sum(**dims) > 0
95
+ lower_mask = is_below.sum(**dims) > 0
96
+
97
+ self.coeff = xr.Dataset(
98
+ {
99
+ "is_below": is_below,
100
+ "is_above": is_above,
101
+ "upper_mask": upper_mask,
102
+ "lower_mask": lower_mask,
103
+ "factor": factor,
104
+ }
105
+ )
106
+
107
+ def apply(self, var, fill_nans=True):
108
+ """Interpolates the variable onto the new depth grid using precomputed
109
+ coefficients for linear interpolation between layers.
110
+
111
+ Parameters
112
+ ----------
113
+ var : xarray.DataArray
114
+ The input data to be regridded along the depth dimension. This should be
115
+ an array with the same depth coordinates as the original grid.
116
+ fill_nans : bool, optional
117
+ Whether to fill NaN values in the regridded data. If True (default),
118
+ forward-fill and backward-fill are applied along the 's_rho' dimension to
119
+ ensure there are no NaNs after interpolation.
120
+
121
+ Returns
122
+ -------
123
+ xarray.DataArray
124
+ The regridded data array, interpolated onto the new depth grid. NaN values
125
+ are replaced if `fill_nans=True`, with extrapolation allowed at the surface
126
+ and bottom layers to minimize gaps.
127
+ """
128
+
129
+ dims = {"dim": self.depth_dim}
130
+
131
+ var_below = var.where(self.coeff["is_below"]).sum(**dims)
132
+ var_above = var.where(self.coeff["is_above"]).sum(**dims)
133
+
134
+ result = var_below + (var_above - var_below) * self.coeff["factor"]
135
+ if fill_nans:
136
+ result = result.where(self.coeff["upper_mask"], var.isel({dims["dim"]: 0}))
137
+ result = result.where(self.coeff["lower_mask"], var.isel({dims["dim"]: -1}))
138
+ else:
139
+ result = result.where(self.coeff["upper_mask"]).where(
140
+ self.coeff["lower_mask"]
141
+ )
142
+
143
+ return result