roms-tools 1.4.1__py3-none-any.whl → 1.5.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 (252) hide show
  1. roms_tools/_version.py +1 -1
  2. roms_tools/setup/boundary_forcing.py +350 -166
  3. roms_tools/setup/datasets.py +57 -74
  4. roms_tools/setup/download.py +3 -6
  5. roms_tools/setup/fill.py +46 -18
  6. roms_tools/setup/grid.py +74 -113
  7. roms_tools/setup/initial_conditions.py +209 -76
  8. roms_tools/setup/regrid.py +198 -0
  9. roms_tools/setup/surface_forcing.py +167 -80
  10. roms_tools/setup/tides.py +135 -67
  11. roms_tools/setup/topography.py +9 -17
  12. roms_tools/setup/utils.py +251 -77
  13. roms_tools/setup/vertical_coordinate.py +4 -6
  14. roms_tools/tests/test_setup/test_boundary_forcing.py +6 -13
  15. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zattrs +1 -1
  16. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zmetadata +1 -1
  17. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_east/0.0.0 +0 -0
  18. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_north/0.0.0 +0 -0
  19. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_south/0.0.0 +0 -0
  20. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/0.0.0 +0 -0
  21. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_east/0.0.0 +0 -0
  22. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_north/0.0.0 +0 -0
  23. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_south/0.0.0 +0 -0
  24. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/0.0.0 +0 -0
  25. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_east/0.0.0 +0 -0
  26. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_north/0.0.0 +0 -0
  27. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_south/0.0.0 +0 -0
  28. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/0.0.0 +0 -0
  29. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_east/0.0.0 +0 -0
  30. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_north/0.0.0 +0 -0
  31. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_south/0.0.0 +0 -0
  32. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/0.0.0 +0 -0
  33. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_east/0.0.0 +0 -0
  34. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_north/0.0.0 +0 -0
  35. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_south/0.0.0 +0 -0
  36. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/0.0.0 +0 -0
  37. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_east/0.0.0 +0 -0
  38. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_north/0.0.0 +0 -0
  39. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_south/0.0.0 +0 -0
  40. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/0.0.0 +0 -0
  41. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_east/0.0.0 +0 -0
  42. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_north/0.0.0 +0 -0
  43. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_south/0.0.0 +0 -0
  44. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/0.0.0 +0 -0
  45. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_east/0.0.0 +0 -0
  46. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_north/0.0.0 +0 -0
  47. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_south/0.0.0 +0 -0
  48. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/0.0.0 +0 -0
  49. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_east/0.0.0 +0 -0
  50. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_north/0.0.0 +0 -0
  51. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_south/0.0.0 +0 -0
  52. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/0.0.0 +0 -0
  53. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_east/0.0.0 +0 -0
  54. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_north/0.0.0 +0 -0
  55. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_south/0.0.0 +0 -0
  56. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/0.0.0 +0 -0
  57. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_east/0.0.0 +0 -0
  58. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_north/0.0.0 +0 -0
  59. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_south/0.0.0 +0 -0
  60. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/0.0.0 +0 -0
  61. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_east/0.0.0 +0 -0
  62. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_north/0.0.0 +0 -0
  63. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_south/0.0.0 +0 -0
  64. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/0.0.0 +0 -0
  65. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_east/0.0.0 +0 -0
  66. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_north/0.0.0 +0 -0
  67. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_south/0.0.0 +0 -0
  68. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/0.0.0 +0 -0
  69. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_east/0.0.0 +0 -0
  70. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_north/0.0.0 +0 -0
  71. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_south/0.0.0 +0 -0
  72. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/0.0.0 +0 -0
  73. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_east/0.0.0 +0 -0
  74. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_north/0.0.0 +0 -0
  75. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_south/0.0.0 +0 -0
  76. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/0.0.0 +0 -0
  77. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_east/0.0.0 +0 -0
  78. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_north/0.0.0 +0 -0
  79. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_south/0.0.0 +0 -0
  80. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/0.0.0 +0 -0
  81. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_east/0.0.0 +0 -0
  82. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_north/0.0.0 +0 -0
  83. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_south/0.0.0 +0 -0
  84. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/0.0.0 +0 -0
  85. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_east/0.0.0 +0 -0
  86. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_north/0.0.0 +0 -0
  87. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_south/0.0.0 +0 -0
  88. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/0.0.0 +0 -0
  89. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_east/0.0.0 +0 -0
  90. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_north/0.0.0 +0 -0
  91. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_south/0.0.0 +0 -0
  92. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/0.0.0 +0 -0
  93. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_east/0.0.0 +0 -0
  94. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_north/0.0.0 +0 -0
  95. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_south/0.0.0 +0 -0
  96. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/0.0.0 +0 -0
  97. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_east/0.0.0 +0 -0
  98. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_north/0.0.0 +0 -0
  99. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_south/0.0.0 +0 -0
  100. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/0.0.0 +0 -0
  101. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_east/0.0.0 +0 -0
  102. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_north/0.0.0 +0 -0
  103. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_south/0.0.0 +0 -0
  104. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/0.0.0 +0 -0
  105. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_east/0.0.0 +0 -0
  106. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_north/0.0.0 +0 -0
  107. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_south/0.0.0 +0 -0
  108. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/0.0.0 +0 -0
  109. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_east/0.0.0 +0 -0
  110. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_north/0.0.0 +0 -0
  111. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_south/0.0.0 +0 -0
  112. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/0.0.0 +0 -0
  113. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_east/0.0.0 +0 -0
  114. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_north/0.0.0 +0 -0
  115. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_south/0.0.0 +0 -0
  116. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/0.0.0 +0 -0
  117. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_east/0.0.0 +0 -0
  118. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_north/0.0.0 +0 -0
  119. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_south/0.0.0 +0 -0
  120. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/0.0.0 +0 -0
  121. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_east/0.0.0 +0 -0
  122. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_north/0.0.0 +0 -0
  123. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_south/0.0.0 +0 -0
  124. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/0.0.0 +0 -0
  125. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_east/0.0.0 +0 -0
  126. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_north/0.0.0 +0 -0
  127. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_south/0.0.0 +0 -0
  128. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/0.0.0 +0 -0
  129. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_east/0.0.0 +0 -0
  130. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_north/0.0.0 +0 -0
  131. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_south/0.0.0 +0 -0
  132. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/0.0.0 +0 -0
  133. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_east/0.0.0 +0 -0
  134. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_north/0.0.0 +0 -0
  135. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_south/0.0.0 +0 -0
  136. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/0.0.0 +0 -0
  137. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_east/0.0.0 +0 -0
  138. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_north/0.0.0 +0 -0
  139. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_south/0.0.0 +0 -0
  140. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/0.0.0 +0 -0
  141. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/0.0.0 +0 -0
  142. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_north/0.0.0 +0 -0
  143. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_south/0.0.0 +0 -0
  144. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/0.0.0 +0 -0
  145. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zattrs +1 -1
  146. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zmetadata +1 -1
  147. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air_alt/0.0.0 +0 -0
  148. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zattrs +1 -1
  149. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zmetadata +1 -1
  150. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air_alt/0.0.0 +0 -0
  151. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zattrs +1 -1
  152. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/.zmetadata +1 -1
  153. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_east/0.0.0 +0 -0
  154. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_north/0.0.0 +0 -0
  155. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/0.0.0 +0 -0
  156. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_west/0.0.0 +0 -0
  157. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/0.0.0 +0 -0
  158. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_north/0.0.0 +0 -0
  159. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/0.0.0 +0 -0
  160. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_west/0.0.0 +0 -0
  161. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/0.0.0 +0 -0
  162. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_north/0.0.0 +0 -0
  163. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_south/0.0.0 +0 -0
  164. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/0.0.0 +0 -0
  165. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/0.0 +0 -0
  166. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_north/0.0 +0 -0
  167. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_south/0.0 +0 -0
  168. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/0.0 +0 -0
  169. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/0.0.0 +0 -0
  170. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/0.0.0 +0 -0
  171. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/0.0.0 +0 -0
  172. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/0.0.0 +0 -0
  173. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/0.0 +0 -0
  174. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/0.0 +0 -0
  175. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/0.0 +0 -0
  176. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/0.0 +0 -0
  177. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_east/0.0 +0 -0
  178. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zeta_south/0.0 +0 -0
  179. roms_tools/tests/test_setup/test_data/grid.zarr/.zattrs +2 -2
  180. roms_tools/tests/test_setup/test_data/grid.zarr/.zmetadata +2 -62
  181. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zattrs +2 -2
  182. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zmetadata +2 -62
  183. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zattrs +1 -1
  184. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zmetadata +1 -1
  185. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK/0.0.0.0 +0 -0
  186. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK_ALT_CO2/0.0.0.0 +0 -0
  187. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC/0.0.0.0 +0 -0
  188. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC_ALT_CO2/0.0.0.0 +0 -0
  189. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOC/0.0.0.0 +0 -0
  190. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOCr/0.0.0.0 +0 -0
  191. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DON/0.0.0.0 +0 -0
  192. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DONr/0.0.0.0 +0 -0
  193. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOP/0.0.0.0 +0 -0
  194. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOPr/0.0.0.0 +0 -0
  195. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Fe/0.0.0.0 +0 -0
  196. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Lig/0.0.0.0 +0 -0
  197. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NH4/0.0.0.0 +0 -0
  198. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NO3/0.0.0.0 +0 -0
  199. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/O2/0.0.0.0 +0 -0
  200. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/PO4/0.0.0.0 +0 -0
  201. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/SiO3/0.0.0.0 +0 -0
  202. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatC/0.0.0.0 +0 -0
  203. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatChl/0.0.0.0 +0 -0
  204. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatFe/0.0.0.0 +0 -0
  205. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatP/0.0.0.0 +0 -0
  206. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatSi/0.0.0.0 +0 -0
  207. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazC/0.0.0.0 +0 -0
  208. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazChl/0.0.0.0 +0 -0
  209. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazFe/0.0.0.0 +0 -0
  210. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazP/0.0.0.0 +0 -0
  211. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/salt/0.0.0.0 +0 -0
  212. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spC/0.0.0.0 +0 -0
  213. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spCaCO3/0.0.0.0 +0 -0
  214. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spChl/0.0.0.0 +0 -0
  215. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spFe/0.0.0.0 +0 -0
  216. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spP/0.0.0.0 +0 -0
  217. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/temp/0.0.0.0 +0 -0
  218. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/u/0.0.0.0 +0 -0
  219. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ubar/0.0.0 +0 -0
  220. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/v/0.0.0.0 +0 -0
  221. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/vbar/0.0.0 +0 -0
  222. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zeta/0.0.0 +0 -0
  223. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zooC/0.0.0.0 +0 -0
  224. roms_tools/tests/test_setup/test_datasets.py +8 -18
  225. roms_tools/tests/test_setup/test_fill.py +43 -14
  226. roms_tools/tests/test_setup/test_grid.py +9 -9
  227. roms_tools/tests/test_setup/test_initial_conditions.py +4 -7
  228. roms_tools/tests/test_setup/test_regrid.py +59 -0
  229. roms_tools/tests/test_setup/test_surface_forcing.py +74 -56
  230. roms_tools/tests/test_setup/test_tides.py +6 -10
  231. roms_tools/tests/test_setup/test_topography.py +2 -4
  232. roms_tools/tests/test_setup/test_vertical_coordinate.py +2 -6
  233. roms_tools/tests/test_utils.py +30 -30
  234. roms_tools/utils.py +6 -7
  235. {roms_tools-1.4.1.dist-info → roms_tools-1.5.0.dist-info}/METADATA +2 -2
  236. {roms_tools-1.4.1.dist-info → roms_tools-1.5.0.dist-info}/RECORD +239 -250
  237. roms_tools/setup/mixins.py +0 -231
  238. roms_tools/tests/test_setup/test_data/grid.zarr/lat_psi/.zarray +0 -22
  239. roms_tools/tests/test_setup/test_data/grid.zarr/lat_psi/.zattrs +0 -8
  240. roms_tools/tests/test_setup/test_data/grid.zarr/lat_psi/0.0 +0 -0
  241. roms_tools/tests/test_setup/test_data/grid.zarr/lon_psi/.zarray +0 -22
  242. roms_tools/tests/test_setup/test_data/grid.zarr/lon_psi/.zattrs +0 -8
  243. roms_tools/tests/test_setup/test_data/grid.zarr/lon_psi/0.0 +0 -0
  244. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_psi/.zarray +0 -22
  245. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_psi/.zattrs +0 -8
  246. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_psi/0.0 +0 -0
  247. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_psi/.zarray +0 -22
  248. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_psi/.zattrs +0 -8
  249. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_psi/0.0 +0 -0
  250. {roms_tools-1.4.1.dist-info → roms_tools-1.5.0.dist-info}/LICENSE +0 -0
  251. {roms_tools-1.4.1.dist-info → roms_tools-1.5.0.dist-info}/WHEEL +0 -0
  252. {roms_tools-1.4.1.dist-info → roms_tools-1.5.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.4.1"
2
+ __version__ = "1.5.0"
@@ -6,16 +6,21 @@ import importlib.metadata
6
6
  from typing import Dict, Union, List
7
7
  from dataclasses import dataclass, field, asdict
8
8
  from roms_tools.setup.grid import Grid
9
- from roms_tools.setup.mixins import ROMSToolsMixins
9
+ from roms_tools.setup.fill import _lateral_fill
10
+ from roms_tools.setup.regrid import _lateral_regrid, _vertical_regrid
10
11
  from datetime import datetime
11
12
  from roms_tools.setup.datasets import GLORYSDataset, CESMBGCDataset
12
13
  from roms_tools.setup.utils import (
13
14
  nan_check,
14
15
  substitute_nans_by_fillvalue,
15
16
  get_variable_metadata,
16
- get_boundary_info,
17
17
  group_dataset,
18
18
  save_datasets,
19
+ get_target_coords,
20
+ rotate_velocities,
21
+ compute_barotropic_velocity,
22
+ _extrapolate_deepest_to_bottom,
23
+ transpose_dimensions,
19
24
  )
20
25
  from roms_tools.setup.plot import _section_plot, _line_plot
21
26
  import matplotlib.pyplot as plt
@@ -23,9 +28,8 @@ from pathlib import Path
23
28
 
24
29
 
25
30
  @dataclass(frozen=True, kw_only=True)
26
- class BoundaryForcing(ROMSToolsMixins):
27
- """
28
- Represents boundary forcing input data for ROMS.
31
+ class BoundaryForcing:
32
+ """Represents boundary forcing input data for ROMS.
29
33
 
30
34
  Parameters
31
35
  ----------
@@ -38,21 +42,27 @@ class BoundaryForcing(ROMSToolsMixins):
38
42
  boundaries : Dict[str, bool], optional
39
43
  Dictionary specifying which boundaries are forced (south, east, north, west). Default is all True.
40
44
  source : Dict[str, Union[str, Path, List[Union[str, Path]]], bool]
41
- Dictionary specifying the source of the boundary forcing data:
42
- - "name" (str): Name of the data source (e.g., "GLORYS").
43
- - "path" (Union[str, Path, List[Union[str, Path]]]): The path to the raw data file(s). Can be a single string (with or without wildcards),
44
- a single Path object, or a list of strings or Path objects containing multiple files.
45
- - "climatology" (bool): Indicates if the data is climatology data. Defaults to False.
45
+ Dictionary specifying the source of the boundary forcing data. Keys include:
46
+
47
+ - "name" (str): Name of the data source (e.g., "GLORYS").
48
+ - "path" (Union[str, Path, List[Union[str, Path]]]): The path to the raw data file(s). This can be:
49
+
50
+ - A single string (with or without wildcards).
51
+ - A single Path object.
52
+ - A list of strings or Path objects containing multiple files.
53
+ - "climatology" (bool): Indicates if the data is climatology data. Defaults to False.
54
+
55
+ type : str
56
+ Specifies the type of forcing data. Options are:
57
+
58
+ - "physics": for physical atmospheric forcing.
59
+ - "bgc": for biogeochemical forcing.
60
+
46
61
  model_reference_date : datetime, optional
47
62
  Reference date for the model. Default is January 1, 2000.
48
63
  use_dask: bool, optional
49
64
  Indicates whether to use dask for processing. If True, data is processed with dask; if False, data is processed eagerly. Defaults to False.
50
65
 
51
- Attributes
52
- ----------
53
- ds : xr.Dataset
54
- Xarray Dataset containing the boundary forcing data.
55
-
56
66
  Examples
57
67
  --------
58
68
  >>> boundary_forcing = BoundaryForcing(
@@ -86,33 +96,115 @@ class BoundaryForcing(ROMSToolsMixins):
86
96
  def __post_init__(self):
87
97
 
88
98
  self._input_checks()
89
- lon, lat, angle, straddle = super().get_target_lon_lat()
99
+ target_coords = get_target_coords(self.grid)
90
100
 
91
101
  data = self._get_data()
92
102
  data.choose_subdomain(
93
- latitude_range=[lat.min().values, lat.max().values],
94
- longitude_range=[lon.min().values, lon.max().values],
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
+ ],
95
111
  margin=2,
96
- straddle=straddle,
112
+ straddle=target_coords["straddle"],
97
113
  )
98
114
 
99
- if self.type == "physics":
100
- vars_2d = ["zeta"]
101
- vars_3d = ["temp", "salt", "u", "v"]
102
- elif self.type == "bgc":
103
- vars_2d = []
104
- vars_3d = data.var_names.keys()
105
-
106
- data_vars = super().regrid_data(data, vars_2d, vars_3d, lon, lat)
115
+ variable_info = self._set_variable_info(data)
107
116
 
108
- if self.type == "physics":
109
- data_vars = super().process_velocities(data_vars, angle, "u", "v")
110
- object.__setattr__(data, "data_vars", data_vars)
117
+ data_vars = {}
118
+ data_vars = _extrapolate_deepest_to_bottom(data_vars, data)
119
+ data_vars = _lateral_fill(data_vars, data)
111
120
 
112
- d_meta = get_variable_metadata()
113
121
  bdry_coords = get_boundary_info()
122
+ ds = xr.Dataset()
123
+ for direction in ["south", "east", "north", "west"]:
124
+ if self.boundaries[direction]:
125
+
126
+ bdry_data_vars = data_vars.copy()
127
+
128
+ # lateral regridding of vector fields
129
+ vector_var_names = [
130
+ name for name, info in variable_info.items() if info["is_vector"]
131
+ ]
132
+ if len(vector_var_names) > 0:
133
+ lon = target_coords["lon"].isel(**bdry_coords["vector"][direction])
134
+ 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
137
+ )
138
+ # lateral regridding of tracer fields
139
+ tracer_var_names = [
140
+ name
141
+ for name, info in variable_info.items()
142
+ if not info["is_vector"]
143
+ ]
144
+ if len(tracer_var_names) > 0:
145
+ lon = target_coords["lon"].isel(**bdry_coords["rho"][direction])
146
+ 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
149
+ )
150
+
151
+ # rotation of velocities and interpolation to u/v points
152
+ if "u" in variable_info and "v" in variable_info:
153
+ angle = target_coords["angle"].isel(
154
+ **bdry_coords["vector"][direction]
155
+ )
156
+ (bdry_data_vars["u"], bdry_data_vars["v"],) = rotate_velocities(
157
+ bdry_data_vars["u"],
158
+ bdry_data_vars["v"],
159
+ angle,
160
+ interpolate=True,
161
+ )
162
+
163
+ # 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"]
167
+ if location in ["u", "v"]:
168
+ bdry_data_vars[var] = bdry_data_vars[var].isel(
169
+ **bdry_coords[location][direction]
170
+ )
171
+
172
+ # vertical regridding
173
+ for location in ["rho", "u", "v"]:
174
+ var_names = [
175
+ name
176
+ for name, info in variable_info.items()
177
+ if info["location"] == location and info["is_3d"]
178
+ ]
179
+ if len(var_names) > 0:
180
+ bdry_data_vars = _vertical_regrid(
181
+ data,
182
+ self.grid.ds[f"layer_depth_{location}"].isel(
183
+ **bdry_coords[location][direction],
184
+ ),
185
+ bdry_data_vars,
186
+ var_names,
187
+ )
188
+
189
+ # compute barotropic velocities
190
+ 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]
196
+ ),
197
+ )
198
+
199
+ # Reorder dimensions
200
+ for var in bdry_data_vars.keys():
201
+ bdry_data_vars[var] = transpose_dimensions(bdry_data_vars[var])
202
+
203
+ # Write the boundary data into dataset
204
+ ds = self._write_into_dataset(direction, bdry_data_vars, ds)
114
205
 
115
- ds = self._write_into_dataset(data, d_meta, bdry_coords)
206
+ # Add global information
207
+ ds = self._add_global_metadata(data, ds)
116
208
 
117
209
  # NaN values at wet points indicate that the raw data did not cover the domain, and the following will raise a ValueError
118
210
  # this check works only for 2D fields because for 3D I extrapolate to bottom which eliminates NaNs
@@ -182,37 +274,86 @@ class BoundaryForcing(ROMSToolsMixins):
182
274
 
183
275
  return data
184
276
 
185
- def _write_into_dataset(self, data, d_meta, bdry_coords):
277
+ def _set_variable_info(self, data):
278
+ """Sets up a dictionary with metadata for variables based on the type of data
279
+ (physics or BGC).
186
280
 
187
- # save in new dataset
188
- ds = xr.Dataset()
281
+ The dictionary contains the following information:
282
+ - `location`: Where the variable resides in the grid (e.g., rho, u, or v points).
283
+ - `is_vector`: Whether the variable is part of a vector (True for velocity components like 'u' and 'v').
284
+ - `vector_pair`: For vector variables, this indicates the associated variable that forms the vector (e.g., 'u' and 'v').
285
+ - `is_3d`: Indicates whether the variable is 3D (True for variables like 'temp' and 'salt') or 2D (False for 'zeta').
189
286
 
190
- for direction in ["south", "east", "north", "west"]:
191
- if self.boundaries[direction]:
287
+ Returns
288
+ -------
289
+ dict
290
+ A dictionary where the keys are variable names and the values are dictionaries of metadata
291
+ about each variable, including 'location', 'is_vector', 'vector_pair', and 'is_3d'.
292
+ """
293
+ default_info = {
294
+ "location": "rho",
295
+ "is_vector": False,
296
+ "vector_pair": None,
297
+ "is_3d": True,
298
+ }
192
299
 
193
- for var in data.data_vars.keys():
194
- if var in ["u", "ubar"]:
195
- ds[f"{var}_{direction}"] = (
196
- data.data_vars[var]
197
- .isel(**bdry_coords["u"][direction])
198
- .astype(np.float32)
199
- )
200
- elif var in ["v", "vbar"]:
201
- ds[f"{var}_{direction}"] = (
202
- data.data_vars[var]
203
- .isel(**bdry_coords["v"][direction])
204
- .astype(np.float32)
205
- )
206
- else:
207
- ds[f"{var}_{direction}"] = (
208
- data.data_vars[var]
209
- .isel(**bdry_coords["rho"][direction])
210
- .astype(np.float32)
211
- )
212
- ds[f"{var}_{direction}"].attrs[
213
- "long_name"
214
- ] = f"{direction}ern boundary {d_meta[var]['long_name']}"
215
- ds[f"{var}_{direction}"].attrs["units"] = d_meta[var]["units"]
300
+ # Define a dictionary for variable names and their associated information
301
+ if self.type == "physics":
302
+ variable_info = {
303
+ "zeta": {
304
+ "location": "rho",
305
+ "is_vector": False,
306
+ "vector_pair": None,
307
+ "is_3d": False,
308
+ },
309
+ "temp": default_info,
310
+ "salt": default_info,
311
+ "u": {
312
+ "location": "u",
313
+ "is_vector": True,
314
+ "vector_pair": "v",
315
+ "is_3d": True,
316
+ },
317
+ "v": {
318
+ "location": "v",
319
+ "is_vector": True,
320
+ "vector_pair": "u",
321
+ "is_3d": True,
322
+ },
323
+ "ubar": {
324
+ "location": "u",
325
+ "is_vector": True,
326
+ "vector_pair": "vbar",
327
+ "is_3d": False,
328
+ },
329
+ "vbar": {
330
+ "location": "v",
331
+ "is_vector": True,
332
+ "vector_pair": "ubar",
333
+ "is_3d": False,
334
+ },
335
+ }
336
+ elif self.type == "bgc":
337
+ variable_info = {}
338
+ for var in data.var_names.keys():
339
+ variable_info[var] = default_info
340
+
341
+ return variable_info
342
+
343
+ def _write_into_dataset(self, direction, data_vars, ds=None):
344
+ if ds is None:
345
+ ds = xr.Dataset()
346
+
347
+ d_meta = get_variable_metadata()
348
+
349
+ for var in data_vars.keys():
350
+ ds[f"{var}_{direction}"] = data_vars[var].astype(np.float32)
351
+
352
+ ds[f"{var}_{direction}"].attrs[
353
+ "long_name"
354
+ ] = f"{direction}ern boundary {d_meta[var]['long_name']}"
355
+
356
+ ds[f"{var}_{direction}"].attrs["units"] = d_meta[var]["units"]
216
357
 
217
358
  # Gracefully handle dropping variables that might not be present
218
359
  variables_to_drop = [
@@ -233,61 +374,10 @@ class BoundaryForcing(ROMSToolsMixins):
233
374
  existing_vars = [var for var in variables_to_drop if var in ds]
234
375
  ds = ds.drop_vars(existing_vars)
235
376
 
236
- ds = self._add_global_metadata(ds)
237
-
238
- # Convert the time coordinate to the format expected by ROMS
239
- if data.climatology:
240
- ds.attrs["climatology"] = str(True)
241
- # Preserve absolute time coordinate for readability
242
- ds = ds.assign_coords(
243
- {"abs_time": np.datetime64(self.model_reference_date) + ds["time"]}
244
- )
245
- # Convert to pandas TimedeltaIndex
246
- timedelta_index = pd.to_timedelta(ds["time"].values)
247
-
248
- # Determine the start of the year for the base_datetime
249
- start_of_year = datetime(self.model_reference_date.year, 1, 1)
250
-
251
- # Calculate the offset from midnight of the new year
252
- offset = self.model_reference_date - start_of_year
253
-
254
- # Convert the timedelta to nanoseconds first, then to days
255
- bry_time = xr.DataArray(
256
- (timedelta_index - offset).view("int64") / 3600 / 24 * 1e-9,
257
- dims="time",
258
- )
259
-
260
- else:
261
- # Preserve absolute time coordinate for readability
262
- ds = ds.assign_coords({"abs_time": ds["time"]})
263
- # TODO: Check if we need to convert from 12:00:00 to 00:00:00 as in matlab scripts
264
- bry_time = (
265
- (ds["time"] - np.datetime64(self.model_reference_date)).astype(
266
- "float64"
267
- )
268
- / 3600
269
- / 24
270
- * 1e-9
271
- )
272
-
273
- ds = ds.assign_coords({"bry_time": bry_time})
274
- ds["bry_time"].attrs[
275
- "long_name"
276
- ] = f"days since {str(self.model_reference_date)}"
277
- ds["bry_time"].encoding["units"] = "days"
278
- ds["bry_time"].attrs["units"] = "days"
279
- ds = ds.swap_dims({"time": "bry_time"})
280
- ds = ds.drop_vars("time")
281
- ds.encoding["unlimited_dims"] = "bry_time"
282
-
283
- if data.climatology:
284
- ds["bry_time"].attrs["cycle_length"] = 365.25
285
-
286
377
  return ds
287
378
 
288
379
  def _get_coordinates(self, direction, point):
289
- """
290
- Retrieve layer and interface depth coordinates for a specified grid boundary.
380
+ """Retrieve layer and interface depth coordinates for a specified grid boundary.
291
381
 
292
382
  This method extracts the layer depth and interface depth coordinates along
293
383
  a specified boundary (north, south, east, or west) and for a specified point
@@ -321,7 +411,7 @@ class BoundaryForcing(ROMSToolsMixins):
321
411
 
322
412
  return layer_depth, interface_depth
323
413
 
324
- def _add_global_metadata(self, ds=None):
414
+ def _add_global_metadata(self, data, ds=None):
325
415
 
326
416
  if ds is None:
327
417
  ds = xr.Dataset()
@@ -341,6 +431,53 @@ class BoundaryForcing(ROMSToolsMixins):
341
431
  ds.attrs["theta_b"] = self.grid.ds.attrs["theta_b"]
342
432
  ds.attrs["hc"] = self.grid.ds.attrs["hc"]
343
433
 
434
+ # Convert the time coordinate to the format expected by ROMS
435
+ if data.climatology:
436
+ ds.attrs["climatology"] = str(True)
437
+ # Preserve absolute time coordinate for readability
438
+ ds = ds.assign_coords(
439
+ {"abs_time": np.datetime64(self.model_reference_date) + ds["time"]}
440
+ )
441
+ # Convert to pandas TimedeltaIndex
442
+ timedelta_index = pd.to_timedelta(ds["time"].values)
443
+
444
+ # Determine the start of the year for the base_datetime
445
+ start_of_year = datetime(self.model_reference_date.year, 1, 1)
446
+
447
+ # Calculate the offset from midnight of the new year
448
+ offset = self.model_reference_date - start_of_year
449
+
450
+ # Convert the timedelta to nanoseconds first, then to days
451
+ bry_time = xr.DataArray(
452
+ (timedelta_index - offset).view("int64") / 3600 / 24 * 1e-9,
453
+ dims="time",
454
+ )
455
+
456
+ else:
457
+ # Preserve absolute time coordinate for readability
458
+ ds = ds.assign_coords({"abs_time": ds["time"]})
459
+ bry_time = (
460
+ (ds["time"] - np.datetime64(self.model_reference_date)).astype(
461
+ "float64"
462
+ )
463
+ / 3600
464
+ / 24
465
+ * 1e-9
466
+ )
467
+
468
+ ds = ds.assign_coords({"bry_time": bry_time})
469
+ ds["bry_time"].attrs[
470
+ "long_name"
471
+ ] = f"days since {str(self.model_reference_date)}"
472
+ ds["bry_time"].encoding["units"] = "days"
473
+ ds["bry_time"].attrs["units"] = "days"
474
+ ds = ds.swap_dims({"time": "bry_time"})
475
+ ds = ds.drop_vars("time")
476
+ ds.encoding["unlimited_dims"] = "bry_time"
477
+
478
+ if data.climatology:
479
+ ds["bry_time"].attrs["cycle_length"] = 365.25
480
+
344
481
  return ds
345
482
 
346
483
  def plot(
@@ -349,52 +486,55 @@ class BoundaryForcing(ROMSToolsMixins):
349
486
  time=0,
350
487
  layer_contours=False,
351
488
  ) -> None:
352
- """
353
- Plot the boundary forcing field for a given time-slice.
489
+ """Plot the boundary forcing field for a given time-slice.
354
490
 
355
491
  Parameters
356
492
  ----------
357
493
  varname : str
358
494
  The name of the boundary forcing field to plot. Options include:
359
- - "temp_{direction}": Potential temperature, where {direction} can be one of ["south", "east", "north", "west"].
360
- - "salt_{direction}": Salinity, where {direction} can be one of ["south", "east", "north", "west"].
361
- - "zeta_{direction}": Sea surface height, where {direction} can be one of ["south", "east", "north", "west"].
362
- - "u_{direction}": u-flux component, where {direction} can be one of ["south", "east", "north", "west"].
363
- - "v_{direction}": v-flux component, where {direction} can be one of ["south", "east", "north", "west"].
364
- - "ubar_{direction}": Vertically integrated u-flux component, where {direction} can be one of ["south", "east", "north", "west"].
365
- - "vbar_{direction}": Vertically integrated v-flux component, where {direction} can be one of ["south", "east", "north", "west"].
366
- - "PO4_{direction}": Dissolved Inorganic Phosphate (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
367
- - "NO3_{direction}": Dissolved Inorganic Nitrate (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
368
- - "SiO3_{direction}": Dissolved Inorganic Silicate (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
369
- - "NH4_{direction}": Dissolved Ammonia (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
370
- - "Fe_{direction}": Dissolved Inorganic Iron (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
371
- - "Lig_{direction}": Iron Binding Ligand (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
372
- - "O2_{direction}": Dissolved Oxygen (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
373
- - "DIC_{direction}": Dissolved Inorganic Carbon (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
374
- - "DIC_ALT_CO2_{direction}": Dissolved Inorganic Carbon, Alternative CO2 (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
375
- - "ALK_{direction}": Alkalinity (meq/m³), where {direction} can be one of ["south", "east", "north", "west"].
376
- - "ALK_ALT_CO2_{direction}": Alkalinity, Alternative CO2 (meq/m³), where {direction} can be one of ["south", "east", "north", "west"].
377
- - "DOC_{direction}": Dissolved Organic Carbon (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
378
- - "DON_{direction}": Dissolved Organic Nitrogen (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
379
- - "DOP_{direction}": Dissolved Organic Phosphorus (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
380
- - "DOPr_{direction}": Refractory Dissolved Organic Phosphorus (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
381
- - "DONr_{direction}": Refractory Dissolved Organic Nitrogen (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
382
- - "DOCr_{direction}": Refractory Dissolved Organic Carbon (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
383
- - "zooC_{direction}": Zooplankton Carbon (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
384
- - "spChl_{direction}": Small Phytoplankton Chlorophyll (mg/m³), where {direction} can be one of ["south", "east", "north", "west"].
385
- - "spC_{direction}": Small Phytoplankton Carbon (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
386
- - "spP_{direction}": Small Phytoplankton Phosphorous (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
387
- - "spFe_{direction}": Small Phytoplankton Iron (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
388
- - "spCaCO3_{direction}": Small Phytoplankton CaCO3 (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
389
- - "diatChl_{direction}": Diatom Chlorophyll (mg/m³), where {direction} can be one of ["south", "east", "north", "west"].
390
- - "diatC_{direction}": Diatom Carbon (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
391
- - "diatP_{direction}": Diatom Phosphorus (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
392
- - "diatFe_{direction}": Diatom Iron (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
393
- - "diatSi_{direction}": Diatom Silicate (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
394
- - "diazChl_{direction}": Diazotroph Chlorophyll (mg/m³), where {direction} can be one of ["south", "east", "north", "west"].
395
- - "diazC_{direction}": Diazotroph Carbon (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
396
- - "diazP_{direction}": Diazotroph Phosphorus (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
397
- - "diazFe_{direction}": Diazotroph Iron (mmol/m³), where {direction} can be one of ["south", "east", "north", "west"].
495
+
496
+ - "temp_{direction}": Potential temperature,
497
+ - "salt_{direction}": Salinity,
498
+ - "zeta_{direction}": Sea surface height,
499
+ - "u_{direction}": u-flux component,
500
+ - "v_{direction}": v-flux component,
501
+ - "ubar_{direction}": Vertically integrated u-flux component,
502
+ - "vbar_{direction}": Vertically integrated v-flux component,
503
+ - "PO4_{direction}": Dissolved Inorganic Phosphate (mmol/m³),
504
+ - "NO3_{direction}": Dissolved Inorganic Nitrate (mmol/m³),
505
+ - "SiO3_{direction}": Dissolved Inorganic Silicate (mmol/m³),
506
+ - "NH4_{direction}": Dissolved Ammonia (mmol/m³),
507
+ - "Fe_{direction}": Dissolved Inorganic Iron (mmol/m³),
508
+ - "Lig_{direction}": Iron Binding Ligand (mmol/m³),
509
+ - "O2_{direction}": Dissolved Oxygen (mmol/m³),
510
+ - "DIC_{direction}": Dissolved Inorganic Carbon (mmol/m³),
511
+ - "DIC_ALT_CO2_{direction}": Dissolved Inorganic Carbon, Alternative CO2 (mmol/m³),
512
+ - "ALK_{direction}": Alkalinity (meq/m³),
513
+ - "ALK_ALT_CO2_{direction}": Alkalinity, Alternative CO2 (meq/m³),
514
+ - "DOC_{direction}": Dissolved Organic Carbon (mmol/m³),
515
+ - "DON_{direction}": Dissolved Organic Nitrogen (mmol/m³),
516
+ - "DOP_{direction}": Dissolved Organic Phosphorus (mmol/m³),
517
+ - "DOPr_{direction}": Refractory Dissolved Organic Phosphorus (mmol/m³),
518
+ - "DONr_{direction}": Refractory Dissolved Organic Nitrogen (mmol/m³),
519
+ - "DOCr_{direction}": Refractory Dissolved Organic Carbon (mmol/m³),
520
+ - "zooC_{direction}": Zooplankton Carbon (mmol/m³),
521
+ - "spChl_{direction}": Small Phytoplankton Chlorophyll (mg/m³),
522
+ - "spC_{direction}": Small Phytoplankton Carbon (mmol/m³),
523
+ - "spP_{direction}": Small Phytoplankton Phosphorous (mmol/m³),
524
+ - "spFe_{direction}": Small Phytoplankton Iron (mmol/m³),
525
+ - "spCaCO3_{direction}": Small Phytoplankton CaCO3 (mmol/m³),
526
+ - "diatChl_{direction}": Diatom Chlorophyll (mg/m³),
527
+ - "diatC_{direction}": Diatom Carbon (mmol/m³),
528
+ - "diatP_{direction}": Diatom Phosphorus (mmol/m³),
529
+ - "diatFe_{direction}": Diatom Iron (mmol/m³),
530
+ - "diatSi_{direction}": Diatom Silicate (mmol/m³),
531
+ - "diazChl_{direction}": Diazotroph Chlorophyll (mg/m³),
532
+ - "diazC_{direction}": Diazotroph Carbon (mmol/m³),
533
+ - "diazP_{direction}": Diazotroph Phosphorus (mmol/m³),
534
+ - "diazFe_{direction}": Diazotroph Iron (mmol/m³),
535
+
536
+ where {direction} can be one of ["south", "east", "north", "west"].
537
+
398
538
  time : int, optional
399
539
  The time index to plot. Default is 0.
400
540
  layer_contours : bool, optional
@@ -468,21 +608,22 @@ class BoundaryForcing(ROMSToolsMixins):
468
608
  def save(
469
609
  self, filepath: Union[str, Path], np_eta: int = None, np_xi: int = None
470
610
  ) -> None:
471
- """
472
- Save the boundary forcing fields to netCDF4 files.
611
+ """Save the boundary forcing fields to netCDF4 files.
473
612
 
474
613
  This method saves the dataset by grouping it into subsets based on the data frequency. The subsets are then written
475
614
  to one or more netCDF4 files. The filenames of the output files reflect the temporal coverage of the data.
476
615
 
477
616
  There are two modes of saving the dataset:
478
617
 
479
- 1. **Single File Mode (default)**:
480
- - If both `np_eta` and `np_xi` are `None`, the entire dataset, divided by temporal subsets, is saved as a single netCDF4 file
481
- with the base filename specified by `filepath.nc`.
618
+ 1. **Single File Mode (default)**:
482
619
 
483
- 2. **Partitioned Mode**:
484
- - If either `np_eta` or `np_xi` is specified, the dataset is divided into spatial tiles along the eta-axis and xi-axis.
485
- - Each spatial tile is saved as a separate netCDF4 file.
620
+ If both `np_eta` and `np_xi` are `None`, the entire dataset, divided by temporal subsets, is saved as a single netCDF4 file
621
+ with the base filename specified by `filepath.nc`.
622
+
623
+ 2. **Partitioned Mode**:
624
+
625
+ - If either `np_eta` or `np_xi` is specified, the dataset is divided into spatial tiles along the eta-axis and xi-axis.
626
+ - Each spatial tile is saved as a separate netCDF4 file.
486
627
 
487
628
  Parameters
488
629
  ----------
@@ -516,8 +657,8 @@ class BoundaryForcing(ROMSToolsMixins):
516
657
  return saved_filenames
517
658
 
518
659
  def to_yaml(self, filepath: Union[str, Path]) -> None:
519
- """
520
- Export the parameters of the class to a YAML file, including the version of roms-tools.
660
+ """Export the parameters of the class to a YAML file, including the version of
661
+ roms-tools.
521
662
 
522
663
  Parameters
523
664
  ----------
@@ -568,8 +709,7 @@ class BoundaryForcing(ROMSToolsMixins):
568
709
  def from_yaml(
569
710
  cls, filepath: Union[str, Path], use_dask: bool = False
570
711
  ) -> "BoundaryForcing":
571
- """
572
- Create an instance of the BoundaryForcing class from a YAML file.
712
+ """Create an instance of the BoundaryForcing class from a YAML file.
573
713
 
574
714
  Parameters
575
715
  ----------
@@ -614,3 +754,47 @@ class BoundaryForcing(ROMSToolsMixins):
614
754
 
615
755
  # Create and return an instance of InitialConditions
616
756
  return cls(grid=grid, **boundary_forcing_data, use_dask=use_dask)
757
+
758
+
759
+ def get_boundary_info():
760
+ """This function provides information about the boundary points for the rho, u, and
761
+ v variables on the grid, specifying the indices for the south, east, north, and west
762
+ boundaries.
763
+
764
+ Returns
765
+ -------
766
+ dict
767
+ A dictionary where keys are variable types ("rho", "u", "v"), and values
768
+ are nested dictionaries mapping directions ("south", "east", "north", "west")
769
+ to the corresponding boundary coordinates.
770
+ """
771
+
772
+ # Boundary coordinates
773
+ bdry_coords = {
774
+ "rho": {
775
+ "south": {"eta_rho": 0},
776
+ "east": {"xi_rho": -1},
777
+ "north": {"eta_rho": -1},
778
+ "west": {"xi_rho": 0},
779
+ },
780
+ "u": {
781
+ "south": {"eta_rho": 0},
782
+ "east": {"xi_u": -1},
783
+ "north": {"eta_rho": -1},
784
+ "west": {"xi_u": 0},
785
+ },
786
+ "v": {
787
+ "south": {"eta_v": 0},
788
+ "east": {"xi_rho": -1},
789
+ "north": {"eta_v": -1},
790
+ "west": {"xi_rho": 0},
791
+ },
792
+ "vector": {
793
+ "south": {"eta_rho": [0, 1]},
794
+ "east": {"xi_rho": [-2, -1]},
795
+ "north": {"eta_rho": [-2, -1]},
796
+ "west": {"xi_rho": [0, 1]},
797
+ },
798
+ }
799
+
800
+ return bdry_coords