roms-tools 1.5.0__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 (238) hide show
  1. roms_tools/_version.py +1 -1
  2. roms_tools/setup/boundary_forcing.py +226 -85
  3. roms_tools/setup/datasets.py +169 -39
  4. roms_tools/setup/fill.py +0 -36
  5. roms_tools/setup/initial_conditions.py +90 -69
  6. roms_tools/setup/regrid.py +43 -98
  7. roms_tools/setup/surface_forcing.py +68 -67
  8. roms_tools/setup/tides.py +60 -45
  9. roms_tools/setup/utils.py +25 -53
  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/ALK_ALT_CO2_east/0.0.0 +0 -0
  12. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_south/0.0.0 +0 -0
  13. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/0.0.0 +0 -0
  14. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_east/0.0.0 +0 -0
  15. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_south/0.0.0 +0 -0
  16. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/0.0.0 +0 -0
  17. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_east/0.0.0 +0 -0
  18. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_south/0.0.0 +0 -0
  19. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/0.0.0 +0 -0
  20. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_east/0.0.0 +0 -0
  21. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_south/0.0.0 +0 -0
  22. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/0.0.0 +0 -0
  23. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_east/0.0.0 +0 -0
  24. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_south/0.0.0 +0 -0
  25. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/0.0.0 +0 -0
  26. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_east/0.0.0 +0 -0
  27. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_south/0.0.0 +0 -0
  28. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/0.0.0 +0 -0
  29. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_east/0.0.0 +0 -0
  30. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_south/0.0.0 +0 -0
  31. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/0.0.0 +0 -0
  32. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_east/0.0.0 +0 -0
  33. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_south/0.0.0 +0 -0
  34. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/0.0.0 +0 -0
  35. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_east/0.0.0 +0 -0
  36. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_south/0.0.0 +0 -0
  37. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/0.0.0 +0 -0
  38. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_east/0.0.0 +0 -0
  39. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_south/0.0.0 +0 -0
  40. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/0.0.0 +0 -0
  41. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_east/0.0.0 +0 -0
  42. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_south/0.0.0 +0 -0
  43. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/0.0.0 +0 -0
  44. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_east/0.0.0 +0 -0
  45. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_south/0.0.0 +0 -0
  46. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/0.0.0 +0 -0
  47. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_east/0.0.0 +0 -0
  48. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_south/0.0.0 +0 -0
  49. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/0.0.0 +0 -0
  50. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_east/0.0.0 +0 -0
  51. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_south/0.0.0 +0 -0
  52. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/0.0.0 +0 -0
  53. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_east/0.0.0 +0 -0
  54. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_south/0.0.0 +0 -0
  55. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/0.0.0 +0 -0
  56. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_east/0.0.0 +0 -0
  57. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_south/0.0.0 +0 -0
  58. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/0.0.0 +0 -0
  59. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_east/0.0.0 +0 -0
  60. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_south/0.0.0 +0 -0
  61. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/0.0.0 +0 -0
  62. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_east/0.0.0 +0 -0
  63. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_south/0.0.0 +0 -0
  64. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/0.0.0 +0 -0
  65. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_east/0.0.0 +0 -0
  66. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_south/0.0.0 +0 -0
  67. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/0.0.0 +0 -0
  68. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_east/0.0.0 +0 -0
  69. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_south/0.0.0 +0 -0
  70. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/0.0.0 +0 -0
  71. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_east/0.0.0 +0 -0
  72. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_south/0.0.0 +0 -0
  73. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/0.0.0 +0 -0
  74. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_east/0.0.0 +0 -0
  75. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_south/0.0.0 +0 -0
  76. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/0.0.0 +0 -0
  77. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_east/0.0.0 +0 -0
  78. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_south/0.0.0 +0 -0
  79. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/0.0.0 +0 -0
  80. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_east/0.0.0 +0 -0
  81. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_south/0.0.0 +0 -0
  82. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/0.0.0 +0 -0
  83. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_east/0.0.0 +0 -0
  84. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_south/0.0.0 +0 -0
  85. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/0.0.0 +0 -0
  86. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_east/0.0.0 +0 -0
  87. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_south/0.0.0 +0 -0
  88. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/0.0.0 +0 -0
  89. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_east/0.0.0 +0 -0
  90. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_south/0.0.0 +0 -0
  91. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/0.0.0 +0 -0
  92. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_east/0.0.0 +0 -0
  93. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_south/0.0.0 +0 -0
  94. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/0.0.0 +0 -0
  95. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_east/0.0.0 +0 -0
  96. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_south/0.0.0 +0 -0
  97. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/0.0.0 +0 -0
  98. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_east/0.0.0 +0 -0
  99. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_south/0.0.0 +0 -0
  100. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/0.0.0 +0 -0
  101. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_east/0.0.0 +0 -0
  102. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_south/0.0.0 +0 -0
  103. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/0.0.0 +0 -0
  104. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/0.0.0 +0 -0
  105. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_south/0.0.0 +0 -0
  106. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/0.0.0 +0 -0
  107. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zattrs +1 -1
  108. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zmetadata +1 -1
  109. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/dust/0.0.0 +0 -0
  110. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/iron/0.0.0 +0 -0
  111. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nhy/0.0.0 +0 -0
  112. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nox/0.0.0 +0 -0
  113. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air/0.0.0 +0 -0
  114. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air_alt/0.0.0 +0 -0
  115. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zattrs +1 -1
  116. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zmetadata +1 -1
  117. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/dust/0.0.0 +0 -0
  118. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/iron/0.0.0 +0 -0
  119. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nhy/0.0.0 +0 -0
  120. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nox/0.0.0 +0 -0
  121. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air/0.0.0 +0 -0
  122. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air_alt/0.0.0 +0 -0
  123. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zmetadata +7 -0
  124. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/abs_time/.zattrs +3 -0
  125. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_east/0.0.0 +0 -0
  126. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/0.0.0 +0 -0
  127. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/0.0.0 +0 -0
  128. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/0.0.0 +0 -0
  129. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/0.0.0 +0 -0
  130. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_north/0.0.0 +0 -0
  131. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_south/0.0.0 +0 -0
  132. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/0.0.0 +0 -0
  133. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/0.0 +0 -0
  134. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_north/0.0 +0 -0
  135. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_south/0.0 +0 -0
  136. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/0.0 +0 -0
  137. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/0.0.0 +0 -0
  138. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/0.0.0 +0 -0
  139. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/0.0.0 +0 -0
  140. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/0.0.0 +0 -0
  141. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/0.0 +0 -0
  142. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/0.0 +0 -0
  143. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/0.0 +0 -0
  144. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/0.0 +0 -0
  145. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/.zattrs +1 -0
  146. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/0.0 +0 -0
  147. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_north/.zattrs +1 -0
  148. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/.zattrs +1 -0
  149. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/0.0 +0 -0
  150. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_west/.zattrs +1 -0
  151. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/.zattrs +1 -1
  152. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/.zmetadata +1 -1
  153. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/Tair/0.0.0 +0 -0
  154. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/lwrad/0.0.0 +0 -0
  155. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/qair/0.0.0 +0 -0
  156. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/rain/0.0.0 +0 -0
  157. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/swrad/0.0.0 +0 -0
  158. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/uwnd/0.0.0 +0 -0
  159. roms_tools/tests/test_setup/test_data/coarse_surface_forcing.zarr/vwnd/0.0.0 +0 -0
  160. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/.zattrs +1 -1
  161. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/.zmetadata +1 -1
  162. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/Tair/0.0.0 +0 -0
  163. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/lwrad/0.0.0 +0 -0
  164. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/qair/0.0.0 +0 -0
  165. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/rain/0.0.0 +0 -0
  166. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/swrad/0.0.0 +0 -0
  167. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/uwnd/0.0.0 +0 -0
  168. roms_tools/tests/test_setup/test_data/corrected_surface_forcing.zarr/vwnd/0.0.0 +0 -0
  169. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK/0.0.0.0 +0 -0
  170. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK_ALT_CO2/0.0.0.0 +0 -0
  171. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC/0.0.0.0 +0 -0
  172. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC_ALT_CO2/0.0.0.0 +0 -0
  173. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOC/0.0.0.0 +0 -0
  174. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOCr/0.0.0.0 +0 -0
  175. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DON/0.0.0.0 +0 -0
  176. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DONr/0.0.0.0 +0 -0
  177. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOP/0.0.0.0 +0 -0
  178. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOPr/0.0.0.0 +0 -0
  179. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Fe/0.0.0.0 +0 -0
  180. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Lig/0.0.0.0 +0 -0
  181. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NH4/0.0.0.0 +0 -0
  182. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NO3/0.0.0.0 +0 -0
  183. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/O2/0.0.0.0 +0 -0
  184. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/PO4/0.0.0.0 +0 -0
  185. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/SiO3/0.0.0.0 +0 -0
  186. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatC/0.0.0.0 +0 -0
  187. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatChl/0.0.0.0 +0 -0
  188. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatFe/0.0.0.0 +0 -0
  189. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatP/0.0.0.0 +0 -0
  190. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatSi/0.0.0.0 +0 -0
  191. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazC/0.0.0.0 +0 -0
  192. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazChl/0.0.0.0 +0 -0
  193. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazFe/0.0.0.0 +0 -0
  194. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazP/0.0.0.0 +0 -0
  195. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/salt/0.0.0.0 +0 -0
  196. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spC/0.0.0.0 +0 -0
  197. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spCaCO3/0.0.0.0 +0 -0
  198. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spChl/0.0.0.0 +0 -0
  199. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spFe/0.0.0.0 +0 -0
  200. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spP/0.0.0.0 +0 -0
  201. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/temp/0.0.0.0 +0 -0
  202. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/u/0.0.0.0 +0 -0
  203. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ubar/0.0.0 +0 -0
  204. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/v/0.0.0.0 +0 -0
  205. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/vbar/0.0.0 +0 -0
  206. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zeta/0.0.0 +0 -0
  207. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zooC/0.0.0.0 +0 -0
  208. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/.zattrs +1 -1
  209. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/.zmetadata +1 -1
  210. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/Tair/0.0.0 +0 -0
  211. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/lwrad/0.0.0 +0 -0
  212. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/qair/0.0.0 +0 -0
  213. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/rain/0.0.0 +0 -0
  214. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/swrad/0.0.0 +0 -0
  215. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/uwnd/0.0.0 +0 -0
  216. roms_tools/tests/test_setup/test_data/surface_forcing.zarr/vwnd/0.0.0 +0 -0
  217. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/.zattrs +1 -1
  218. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/.zmetadata +4 -2
  219. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/omega/.zattrs +3 -1
  220. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/pot_Im/0.0.0 +0 -0
  221. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/pot_Re/0.0.0 +0 -0
  222. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ssh_Im/0.0.0 +0 -0
  223. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ssh_Re/0.0.0 +0 -0
  224. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Im/0.0.0 +0 -0
  225. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Re/0.0.0 +0 -0
  226. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Im/0.0.0 +0 -0
  227. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Re/0.0.0 +0 -0
  228. roms_tools/tests/test_setup/test_datasets.py +79 -21
  229. roms_tools/tests/test_setup/test_fill.py +18 -105
  230. roms_tools/tests/test_setup/test_initial_conditions.py +21 -21
  231. roms_tools/tests/test_setup/test_regrid.py +2 -8
  232. roms_tools/tests/test_setup/test_surface_forcing.py +3 -3
  233. roms_tools/tests/test_setup/test_tides.py +1 -1
  234. {roms_tools-1.5.0.dist-info → roms_tools-1.6.0.dist-info}/METADATA +12 -3
  235. {roms_tools-1.5.0.dist-info → roms_tools-1.6.0.dist-info}/RECORD +238 -238
  236. {roms_tools-1.5.0.dist-info → roms_tools-1.6.0.dist-info}/WHEEL +1 -1
  237. {roms_tools-1.5.0.dist-info → roms_tools-1.6.0.dist-info}/LICENSE +0 -0
  238. {roms_tools-1.5.0.dist-info → roms_tools-1.6.0.dist-info}/top_level.txt +0 -0
roms_tools/_version.py CHANGED
@@ -1,2 +1,2 @@
1
1
  # Do not change! Do not track in version control!
2
- __version__ = "1.5.0"
2
+ __version__ = "1.6.0"
@@ -3,24 +3,24 @@ import numpy as np
3
3
  import pandas as pd
4
4
  import yaml
5
5
  import importlib.metadata
6
+ import warnings
6
7
  from typing import Dict, Union, List
7
8
  from dataclasses import dataclass, field, asdict
8
9
  from roms_tools.setup.grid import Grid
9
- from roms_tools.setup.fill import _lateral_fill
10
- from roms_tools.setup.regrid import _lateral_regrid, _vertical_regrid
10
+ from roms_tools.setup.regrid import LateralRegrid, VerticalRegrid
11
11
  from datetime import datetime
12
12
  from roms_tools.setup.datasets import GLORYSDataset, CESMBGCDataset
13
13
  from roms_tools.setup.utils import (
14
- nan_check,
15
- substitute_nans_by_fillvalue,
16
14
  get_variable_metadata,
17
15
  group_dataset,
18
16
  save_datasets,
19
17
  get_target_coords,
20
18
  rotate_velocities,
21
19
  compute_barotropic_velocity,
22
- _extrapolate_deepest_to_bottom,
23
20
  transpose_dimensions,
21
+ one_dim_fill,
22
+ nan_check,
23
+ substitute_nans_by_fillvalue,
24
24
  )
25
25
  from roms_tools.setup.plot import _section_plot, _line_plot
26
26
  import matplotlib.pyplot as plt
@@ -60,6 +60,10 @@ class BoundaryForcing:
60
60
 
61
61
  model_reference_date : datetime, optional
62
62
  Reference date for the model. Default is January 1, 2000.
63
+ apply_2d_horizontal_fill: bool, optional
64
+ Indicates whether to perform a two-dimensional horizontal fill on the source data prior to regridding to boundaries.
65
+ If `False`, a one-dimensional horizontal fill is performed separately on each of the four regridded boundaries.
66
+ Defaults to `False`.
63
67
  use_dask: bool, optional
64
68
  Indicates whether to use dask for processing. If True, data is processed with dask; if False, data is processed eagerly. Defaults to False.
65
69
 
@@ -89,6 +93,7 @@ class BoundaryForcing:
89
93
  source: Dict[str, Union[str, Path, List[Union[str, Path]]]]
90
94
  type: str = "physics"
91
95
  model_reference_date: datetime = datetime(2000, 1, 1)
96
+ apply_2d_horizontal_fill: bool = False
92
97
  use_dask: bool = False
93
98
 
94
99
  ds: xr.Dataset = field(init=False, repr=False)
@@ -99,31 +104,42 @@ class BoundaryForcing:
99
104
  target_coords = get_target_coords(self.grid)
100
105
 
101
106
  data = self._get_data()
102
- data.choose_subdomain(
103
- latitude_range=[
104
- target_coords["lat"].min().values,
105
- target_coords["lat"].max().values,
106
- ],
107
- longitude_range=[
108
- target_coords["lon"].min().values,
109
- target_coords["lon"].max().values,
110
- ],
111
- margin=2,
112
- straddle=target_coords["straddle"],
113
- )
114
-
115
- variable_info = self._set_variable_info(data)
116
107
 
117
- data_vars = {}
118
- data_vars = _extrapolate_deepest_to_bottom(data_vars, data)
119
- data_vars = _lateral_fill(data_vars, data)
108
+ if self.apply_2d_horizontal_fill:
109
+ data.choose_subdomain(
110
+ target_coords,
111
+ buffer_points=20, # lateral fill needs good buffer from data margin
112
+ )
113
+ data.extrapolate_deepest_to_bottom()
114
+ data.apply_lateral_fill()
120
115
 
116
+ variable_info = self._set_variable_info(data)
121
117
  bdry_coords = get_boundary_info()
122
118
  ds = xr.Dataset()
119
+
123
120
  for direction in ["south", "east", "north", "west"]:
124
121
  if self.boundaries[direction]:
125
122
 
126
- bdry_data_vars = data_vars.copy()
123
+ bdry_target_coords = {
124
+ "lat": target_coords["lat"].isel(
125
+ **bdry_coords["vector"][direction]
126
+ ),
127
+ "lon": target_coords["lon"].isel(
128
+ **bdry_coords["vector"][direction]
129
+ ),
130
+ "straddle": target_coords["straddle"],
131
+ }
132
+
133
+ bdry_data = data.choose_subdomain(
134
+ bdry_target_coords,
135
+ buffer_points=3,
136
+ return_copy=True,
137
+ )
138
+
139
+ if not self.apply_2d_horizontal_fill:
140
+ bdry_data.extrapolate_deepest_to_bottom()
141
+
142
+ processed_fields = {}
127
143
 
128
144
  # lateral regridding of vector fields
129
145
  vector_var_names = [
@@ -132,9 +148,15 @@ class BoundaryForcing:
132
148
  if len(vector_var_names) > 0:
133
149
  lon = target_coords["lon"].isel(**bdry_coords["vector"][direction])
134
150
  lat = target_coords["lat"].isel(**bdry_coords["vector"][direction])
135
- bdry_data_vars = _lateral_regrid(
136
- data, lon, lat, bdry_data_vars, vector_var_names
151
+ lateral_regrid = LateralRegrid(
152
+ {"lat": lat, "lon": lon}, bdry_data.dim_names
137
153
  )
154
+ for var_name in vector_var_names:
155
+ if var_name in bdry_data.var_names.keys():
156
+ processed_fields[var_name] = lateral_regrid.apply(
157
+ bdry_data.ds[bdry_data.var_names[var_name]]
158
+ )
159
+
138
160
  # lateral regridding of tracer fields
139
161
  tracer_var_names = [
140
162
  name
@@ -144,30 +166,38 @@ class BoundaryForcing:
144
166
  if len(tracer_var_names) > 0:
145
167
  lon = target_coords["lon"].isel(**bdry_coords["rho"][direction])
146
168
  lat = target_coords["lat"].isel(**bdry_coords["rho"][direction])
147
- bdry_data_vars = _lateral_regrid(
148
- data, lon, lat, bdry_data_vars, tracer_var_names
169
+ lateral_regrid = LateralRegrid(
170
+ {"lat": lat, "lon": lon}, bdry_data.dim_names
149
171
  )
172
+ for var_name in tracer_var_names:
173
+ if var_name in bdry_data.var_names.keys():
174
+ processed_fields[var_name] = lateral_regrid.apply(
175
+ bdry_data.ds[bdry_data.var_names[var_name]]
176
+ )
150
177
 
151
178
  # rotation of velocities and interpolation to u/v points
152
179
  if "u" in variable_info and "v" in variable_info:
153
180
  angle = target_coords["angle"].isel(
154
181
  **bdry_coords["vector"][direction]
155
182
  )
156
- (bdry_data_vars["u"], bdry_data_vars["v"],) = rotate_velocities(
157
- bdry_data_vars["u"],
158
- bdry_data_vars["v"],
183
+ (processed_fields["u"], processed_fields["v"],) = rotate_velocities(
184
+ processed_fields["u"],
185
+ processed_fields["v"],
159
186
  angle,
160
187
  interpolate=True,
161
188
  )
162
189
 
163
190
  # selection of outermost margin for u/v variables
164
- for var in variable_info.keys():
165
- if var in bdry_data_vars:
166
- location = variable_info[var]["location"]
191
+ for var_name in variable_info.keys():
192
+ if var_name in processed_fields:
193
+ location = variable_info[var_name]["location"]
167
194
  if location in ["u", "v"]:
168
- bdry_data_vars[var] = bdry_data_vars[var].isel(
169
- **bdry_coords[location][direction]
170
- )
195
+ processed_fields[var_name] = processed_fields[
196
+ var_name
197
+ ].isel(**bdry_coords[location][direction])
198
+
199
+ if not self.apply_2d_horizontal_fill:
200
+ processed_fields = apply_1d_horizontal_fill(processed_fields)
171
201
 
172
202
  # vertical regridding
173
203
  for location in ["rho", "u", "v"]:
@@ -177,53 +207,47 @@ class BoundaryForcing:
177
207
  if info["location"] == location and info["is_3d"]
178
208
  ]
179
209
  if len(var_names) > 0:
180
- bdry_data_vars = _vertical_regrid(
181
- data,
210
+ vertical_regrid = VerticalRegrid(
182
211
  self.grid.ds[f"layer_depth_{location}"].isel(
183
- **bdry_coords[location][direction],
212
+ **bdry_coords[location][direction]
184
213
  ),
185
- bdry_data_vars,
186
- var_names,
214
+ bdry_data.ds[bdry_data.dim_names["depth"]],
187
215
  )
216
+ for var_name in var_names:
217
+ if var_name in processed_fields:
218
+ processed_fields[var_name] = vertical_regrid.apply(
219
+ processed_fields[var_name]
220
+ )
188
221
 
189
222
  # compute barotropic velocities
190
223
  if "u" in variable_info and "v" in variable_info:
191
- for var in ["u", "v"]:
192
- bdry_data_vars[f"{var}bar"] = compute_barotropic_velocity(
193
- bdry_data_vars[var],
194
- self.grid.ds[f"interface_depth_{var}"].isel(
195
- **bdry_coords[var][direction]
224
+ for var_name in ["u", "v"]:
225
+ processed_fields[
226
+ f"{var_name}bar"
227
+ ] = compute_barotropic_velocity(
228
+ processed_fields[var_name],
229
+ self.grid.ds[f"interface_depth_{var_name}"].isel(
230
+ **bdry_coords[var_name][direction]
196
231
  ),
197
232
  )
198
233
 
199
234
  # Reorder dimensions
200
- for var in bdry_data_vars.keys():
201
- bdry_data_vars[var] = transpose_dimensions(bdry_data_vars[var])
235
+ for var_name in processed_fields.keys():
236
+ processed_fields[var_name] = transpose_dimensions(
237
+ processed_fields[var_name]
238
+ )
202
239
 
203
240
  # Write the boundary data into dataset
204
- ds = self._write_into_dataset(direction, bdry_data_vars, ds)
241
+ ds = self._write_into_dataset(direction, processed_fields, ds)
205
242
 
206
243
  # Add global information
207
244
  ds = self._add_global_metadata(data, ds)
208
245
 
209
- # NaN values at wet points indicate that the raw data did not cover the domain, and the following will raise a ValueError
210
- # this check works only for 2D fields because for 3D I extrapolate to bottom which eliminates NaNs
211
- for direction in ["south", "east", "north", "west"]:
212
- if self.boundaries[direction]:
213
- if type == "physics":
214
- nan_check(
215
- ds[f"zeta_{direction}"].isel(bry_time=0),
216
- self.grid.ds.mask_rho.isel(**bdry_coords["rho"][direction]),
217
- )
218
- elif type == "bgc":
219
- nan_check(
220
- ds[f"ALK_{direction}"].isel(bry_time=0, s_rho=-1),
221
- self.grid.ds.mask_rho.isel(**bdry_coords["rho"][direction]),
222
- )
246
+ self._validate(ds, variable_info, bdry_coords)
223
247
 
224
248
  # substitute NaNs over land by a fill value to avoid blow-up of ROMS
225
- for var in ds.data_vars:
226
- ds[var] = substitute_nans_by_fillvalue(ds[var])
249
+ for var_name in ds.data_vars:
250
+ ds[var_name] = substitute_nans_by_fillvalue(ds[var_name])
227
251
 
228
252
  object.__setattr__(self, "ds", ds)
229
253
 
@@ -335,25 +359,27 @@ class BoundaryForcing:
335
359
  }
336
360
  elif self.type == "bgc":
337
361
  variable_info = {}
338
- for var in data.var_names.keys():
339
- variable_info[var] = default_info
362
+ for var_name in data.var_names.keys():
363
+ variable_info[var_name] = default_info
340
364
 
341
365
  return variable_info
342
366
 
343
- def _write_into_dataset(self, direction, data_vars, ds=None):
367
+ def _write_into_dataset(self, direction, processed_fields, ds=None):
344
368
  if ds is None:
345
369
  ds = xr.Dataset()
346
370
 
347
371
  d_meta = get_variable_metadata()
348
372
 
349
- for var in data_vars.keys():
350
- ds[f"{var}_{direction}"] = data_vars[var].astype(np.float32)
373
+ for var_name in processed_fields.keys():
374
+ ds[f"{var_name}_{direction}"] = processed_fields[var_name].astype(
375
+ np.float32
376
+ )
351
377
 
352
- ds[f"{var}_{direction}"].attrs[
378
+ ds[f"{var_name}_{direction}"].attrs[
353
379
  "long_name"
354
- ] = f"{direction}ern boundary {d_meta[var]['long_name']}"
380
+ ] = f"{direction}ern boundary {d_meta[var_name]['long_name']}"
355
381
 
356
- ds[f"{var}_{direction}"].attrs["units"] = d_meta[var]["units"]
382
+ ds[f"{var_name}_{direction}"].attrs["units"] = d_meta[var_name]["units"]
357
383
 
358
384
  # Gracefully handle dropping variables that might not be present
359
385
  variables_to_drop = [
@@ -371,7 +397,7 @@ class BoundaryForcing:
371
397
  "lat_v",
372
398
  "lon_v",
373
399
  ]
374
- existing_vars = [var for var in variables_to_drop if var in ds]
400
+ existing_vars = [var_name for var_name in variables_to_drop if var_name in ds]
375
401
  ds = ds.drop_vars(existing_vars)
376
402
 
377
403
  return ds
@@ -480,9 +506,76 @@ class BoundaryForcing:
480
506
 
481
507
  return ds
482
508
 
509
+ def _validate(self, ds, variable_info, bdry_coords):
510
+ """Validate the dataset for NaN values at the first time step based on the fill
511
+ method used.
512
+
513
+ Parameters
514
+ ----------
515
+ ds : xarray.Dataset
516
+ The dataset to validate.
517
+
518
+ variable_info : dict
519
+ A dictionary containing metadata about the variables, including their locations (e.g., 'rho', 'u', 'v').
520
+
521
+ bdry_coords : dict
522
+ A dictionary containing the boundary coordinates for each variable location.
523
+
524
+ Raises
525
+ ------
526
+ ValueError
527
+ If NaN values are found in any of the specified variables at wet points,
528
+ indicating incomplete data coverage.
529
+
530
+ Notes
531
+ -----
532
+ Validation is performed on the initial boundary time step (`bry_time=0`) for each
533
+ variable in the dataset. If the `apply_2d_horizontal_fill` attribute is set to False,
534
+ a warning is issued instead of a strict NaN check, as the data may not be reliably validated.
535
+ Conversely, if `apply_2d_horizontal_fill` is True, a strict NaN check is performed, raising
536
+ a ValueError if any NaN values are detected.
537
+ """
538
+ if self.apply_2d_horizontal_fill:
539
+ # Strict NaN check with ValueError makes sense to be applied
540
+ for var_name in variable_info:
541
+ location = variable_info[var_name]["location"]
542
+
543
+ # Select the appropriate mask based on variable location
544
+ if location == "rho":
545
+ mask = self.grid.ds.mask_rho
546
+ elif location == "u":
547
+ mask = self.grid.ds.mask_u
548
+ elif location == "v":
549
+ mask = self.grid.ds.mask_v
550
+ else:
551
+ continue # Skip if location is not recognized
552
+
553
+ for direction in ["south", "east", "north", "west"]:
554
+ if self.boundaries[direction]:
555
+ bdry_var_name = f"{var_name}_{direction}"
556
+
557
+ # Check for NaN values at the first time step using the nan_check function
558
+ nan_check(
559
+ ds[bdry_var_name].isel(bry_time=0),
560
+ mask.isel(**bdry_coords[location][direction]),
561
+ )
562
+ else:
563
+ # Can't apply strict NaN check because land values haven't been filled before regridding step; instead warn user
564
+ for direction in ["south", "east", "north", "west"]:
565
+ if self.boundaries[direction]:
566
+ for var_name in variable_info:
567
+ bdry_var_name = f"{var_name}_{direction}"
568
+ if ds[bdry_var_name].isel(bry_time=0).isnull().any().values:
569
+ warnings.warn(
570
+ f"NaN values detected in regridded variables along the {direction}ern boundary. This may indicate that the entire boundary is on land in the source data, or that the source data does not cover this boundary.",
571
+ UserWarning,
572
+ )
573
+ # Break after the first warning for this direction to avoid duplicates
574
+ break
575
+
483
576
  def plot(
484
577
  self,
485
- varname,
578
+ var_name,
486
579
  time=0,
487
580
  layer_contours=False,
488
581
  ) -> None:
@@ -490,7 +583,7 @@ class BoundaryForcing:
490
583
 
491
584
  Parameters
492
585
  ----------
493
- varname : str
586
+ var_name : str
494
587
  The name of the boundary forcing field to plot. Options include:
495
588
 
496
589
  - "temp_{direction}": Potential temperature,
@@ -550,37 +643,37 @@ class BoundaryForcing:
550
643
  Raises
551
644
  ------
552
645
  ValueError
553
- If the specified varname is not one of the valid options.
646
+ If the specified var_name is not one of the valid options.
554
647
  """
555
648
 
556
- if varname not in self.ds:
557
- raise ValueError(f"Variable '{varname}' is not found in dataset.")
649
+ if var_name not in self.ds:
650
+ raise ValueError(f"Variable '{var_name}' is not found in dataset.")
558
651
 
559
- field = self.ds[varname].isel(bry_time=time).load()
652
+ field = self.ds[var_name].isel(bry_time=time).load()
560
653
  title = field.long_name
561
654
 
562
655
  if "s_rho" in field.dims:
563
- if varname.startswith(("u_", "ubar_")):
656
+ if var_name.startswith(("u_", "ubar_")):
564
657
  point = "u"
565
- elif varname.startswith(("v_", "vbar_")):
658
+ elif var_name.startswith(("v_", "vbar_")):
566
659
  point = "v"
567
660
  else:
568
661
  point = "rho"
569
- direction = varname.split("_")[-1]
662
+ direction = var_name.split("_")[-1]
570
663
 
571
664
  layer_depth, interface_depth = self._get_coordinates(direction, point)
572
665
 
573
666
  field = field.assign_coords({"layer_depth": layer_depth})
574
667
 
575
668
  # chose colorbar
576
- if varname.startswith(("u", "v", "ubar", "vbar", "zeta")):
669
+ if var_name.startswith(("u", "v", "ubar", "vbar", "zeta")):
577
670
  vmax = max(field.max().values, -field.min().values)
578
671
  vmin = -vmax
579
672
  cmap = plt.colormaps.get_cmap("RdBu_r")
580
673
  else:
581
674
  vmax = field.max().values
582
675
  vmin = field.min().values
583
- if varname.startswith(("temp", "salt")):
676
+ if var_name.startswith(("temp", "salt")):
584
677
  cmap = plt.colormaps.get_cmap("YlOrRd")
585
678
  else:
586
679
  cmap = plt.colormaps.get_cmap("YlGn")
@@ -798,3 +891,51 @@ def get_boundary_info():
798
891
  }
799
892
 
800
893
  return bdry_coords
894
+
895
+
896
+ def apply_1d_horizontal_fill(processed_fields: dict) -> dict:
897
+ """Forward and backward fill NaN values in horizontal direction for open boundaries.
898
+
899
+ Parameters
900
+ ----------
901
+ processed_fields : dict
902
+ A dictionary of variables to be updated, where each value is an
903
+ `xarray.DataArray`.
904
+
905
+ Returns
906
+ -------
907
+ dict of str : xarray.DataArray
908
+ The updated dictionary of variables, with NaN values filled.
909
+
910
+ Raises
911
+ ------
912
+ ValueError
913
+ If more than one horizontal dimension is found or none at all.
914
+ """
915
+
916
+ horizontal_dims = ["eta_rho", "eta_v", "xi_rho", "xi_u"]
917
+
918
+ for var_name in processed_fields.keys():
919
+ selected_horizontal_dim = None
920
+ # Determine the horizontal dimension to fill
921
+ for dim in horizontal_dims:
922
+ if dim in processed_fields[var_name].dims:
923
+ if selected_horizontal_dim is not None:
924
+ raise ValueError(
925
+ f"More than one horizontal dimension found in variable '{var_name}'."
926
+ )
927
+ selected_horizontal_dim = dim
928
+
929
+ if selected_horizontal_dim is None:
930
+ raise ValueError(
931
+ f"No valid horizontal dimension found for variable '{var_name}'."
932
+ )
933
+ # Forward and backward fill in the horizontal direction
934
+ filled = one_dim_fill(
935
+ processed_fields[var_name], selected_horizontal_dim, direction="forward"
936
+ )
937
+ processed_fields[var_name] = one_dim_fill(
938
+ filled, selected_horizontal_dim, direction="backward"
939
+ )
940
+
941
+ return processed_fields