roms-tools 2.4.0__py3-none-any.whl → 2.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 (214) hide show
  1. ci/environment-with-xesmf.yml +16 -0
  2. roms_tools/__init__.py +1 -1
  3. roms_tools/analysis/roms_output.py +339 -234
  4. roms_tools/analysis/utils.py +137 -0
  5. roms_tools/plot.py +353 -214
  6. roms_tools/regrid.py +154 -9
  7. roms_tools/setup/boundary_forcing.py +51 -37
  8. roms_tools/setup/datasets.py +129 -74
  9. roms_tools/setup/grid.py +32 -33
  10. roms_tools/setup/initial_conditions.py +30 -37
  11. roms_tools/setup/nesting.py +238 -64
  12. roms_tools/setup/river_forcing.py +256 -86
  13. roms_tools/setup/surface_forcing.py +40 -28
  14. roms_tools/setup/tides.py +10 -13
  15. roms_tools/setup/topography.py +27 -4
  16. roms_tools/setup/utils.py +28 -12
  17. roms_tools/tests/test_analysis/test_roms_output.py +299 -80
  18. roms_tools/tests/test_regrid.py +85 -2
  19. roms_tools/tests/test_setup/test_boundary_forcing.py +63 -0
  20. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zattrs +3 -1
  21. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/.zmetadata +3 -1
  22. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_east/0.0.0 +0 -0
  23. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_south/0.0.0 +0 -0
  24. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/0.0.0 +0 -0
  25. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_east/0.0.0 +0 -0
  26. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_south/0.0.0 +0 -0
  27. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/0.0.0 +0 -0
  28. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_east/0.0.0 +0 -0
  29. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_south/0.0.0 +0 -0
  30. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/0.0.0 +0 -0
  31. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_east/0.0.0 +0 -0
  32. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_south/0.0.0 +0 -0
  33. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/0.0.0 +0 -0
  34. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_east/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_south/0.0.0 +0 -0
  39. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/0.0.0 +0 -0
  40. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_east/0.0.0 +0 -0
  41. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_south/0.0.0 +0 -0
  42. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/0.0.0 +0 -0
  43. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_east/0.0.0 +0 -0
  44. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_south/0.0.0 +0 -0
  45. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/0.0.0 +0 -0
  46. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_east/0.0.0 +0 -0
  47. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_south/0.0.0 +0 -0
  48. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/0.0.0 +0 -0
  49. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_east/0.0.0 +0 -0
  50. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_south/0.0.0 +0 -0
  51. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/0.0.0 +0 -0
  52. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_east/0.0.0 +0 -0
  53. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_south/0.0.0 +0 -0
  54. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/0.0.0 +0 -0
  55. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_east/0.0.0 +0 -0
  56. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_south/0.0.0 +0 -0
  57. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/0.0.0 +0 -0
  58. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_east/0.0.0 +0 -0
  59. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_north/0.0.0 +0 -0
  60. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_south/0.0.0 +0 -0
  61. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/0.0.0 +0 -0
  62. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_east/0.0.0 +0 -0
  63. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_south/0.0.0 +0 -0
  64. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/0.0.0 +0 -0
  65. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_east/0.0.0 +0 -0
  66. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_south/0.0.0 +0 -0
  67. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/0.0.0 +0 -0
  68. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_east/0.0.0 +0 -0
  69. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_south/0.0.0 +0 -0
  70. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/0.0.0 +0 -0
  71. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_east/0.0.0 +0 -0
  72. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_south/0.0.0 +0 -0
  73. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/0.0.0 +0 -0
  74. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_east/0.0.0 +0 -0
  75. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_north/0.0.0 +0 -0
  76. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_south/0.0.0 +0 -0
  77. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/0.0.0 +0 -0
  78. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_east/0.0.0 +0 -0
  79. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_north/0.0.0 +0 -0
  80. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_south/0.0.0 +0 -0
  81. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/0.0.0 +0 -0
  82. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_east/0.0.0 +0 -0
  83. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_north/0.0.0 +0 -0
  84. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_south/0.0.0 +0 -0
  85. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/0.0.0 +0 -0
  86. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_east/0.0.0 +0 -0
  87. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_north/0.0.0 +0 -0
  88. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_south/0.0.0 +0 -0
  89. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/0.0.0 +0 -0
  90. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_east/0.0.0 +0 -0
  91. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_north/0.0.0 +0 -0
  92. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_south/0.0.0 +0 -0
  93. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/0.0.0 +0 -0
  94. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_east/0.0.0 +0 -0
  95. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_north/0.0.0 +0 -0
  96. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_south/0.0.0 +0 -0
  97. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/0.0.0 +0 -0
  98. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_east/0.0.0 +0 -0
  99. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_north/0.0.0 +0 -0
  100. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_south/0.0.0 +0 -0
  101. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/0.0.0 +0 -0
  102. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_east/0.0.0 +0 -0
  103. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_north/0.0.0 +0 -0
  104. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_south/0.0.0 +0 -0
  105. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/0.0.0 +0 -0
  106. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_east/0.0.0 +0 -0
  107. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_north/0.0.0 +0 -0
  108. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_south/0.0.0 +0 -0
  109. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/0.0.0 +0 -0
  110. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_east/0.0.0 +0 -0
  111. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_north/0.0.0 +0 -0
  112. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_south/0.0.0 +0 -0
  113. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/0.0.0 +0 -0
  114. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_east/0.0.0 +0 -0
  115. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_north/0.0.0 +0 -0
  116. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_south/0.0.0 +0 -0
  117. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/0.0.0 +0 -0
  118. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_east/0.0.0 +0 -0
  119. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_north/0.0.0 +0 -0
  120. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_south/0.0.0 +0 -0
  121. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/0.0.0 +0 -0
  122. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_east/0.0.0 +0 -0
  123. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_north/0.0.0 +0 -0
  124. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_south/0.0.0 +0 -0
  125. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/0.0.0 +0 -0
  126. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_east/0.0.0 +0 -0
  127. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_north/0.0.0 +0 -0
  128. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_south/0.0.0 +0 -0
  129. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/0.0.0 +0 -0
  130. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/0.0.0 +0 -0
  131. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_north/0.0.0 +0 -0
  132. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_south/0.0.0 +0 -0
  133. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/0.0.0 +0 -0
  134. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zattrs +2 -2
  135. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/.zmetadata +8 -7
  136. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/abs_time/.zattrs +1 -0
  137. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/dust/0.0.0 +0 -0
  138. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/dust_time/.zattrs +1 -1
  139. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/iron/0.0.0 +0 -0
  140. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/iron_time/.zattrs +1 -1
  141. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nhy/0.0.0 +0 -0
  142. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nhy_time/.zattrs +1 -1
  143. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nox/0.0.0 +0 -0
  144. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/nox_time/.zattrs +1 -1
  145. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air/0.0.0 +0 -0
  146. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_air_alt/0.0.0 +0 -0
  147. roms_tools/tests/test_setup/test_data/bgc_surface_forcing.zarr/pco2_time/.zattrs +1 -1
  148. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zattrs +2 -2
  149. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/.zmetadata +2 -2
  150. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/dust/0.0.0 +0 -0
  151. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/iron/0.0.0 +0 -0
  152. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nhy/0.0.0 +0 -0
  153. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/nox/0.0.0 +0 -0
  154. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air/0.0.0 +0 -0
  155. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_climatology.zarr/pco2_air_alt/0.0.0 +0 -0
  156. roms_tools/tests/test_setup/test_data/grid.zarr/.zattrs +1 -1
  157. roms_tools/tests/test_setup/test_data/grid.zarr/.zmetadata +2 -2
  158. roms_tools/tests/test_setup/test_data/grid.zarr/angle/0.0 +0 -0
  159. roms_tools/tests/test_setup/test_data/grid.zarr/angle_coarse/0.0 +0 -0
  160. roms_tools/tests/test_setup/test_data/grid.zarr/f/0.0 +0 -0
  161. roms_tools/tests/test_setup/test_data/grid.zarr/h/.zattrs +1 -1
  162. roms_tools/tests/test_setup/test_data/grid.zarr/h/0.0 +0 -0
  163. roms_tools/tests/test_setup/test_data/grid.zarr/lat_coarse/0.0 +0 -0
  164. roms_tools/tests/test_setup/test_data/grid.zarr/lat_rho/0.0 +0 -0
  165. roms_tools/tests/test_setup/test_data/grid.zarr/lat_u/0.0 +0 -0
  166. roms_tools/tests/test_setup/test_data/grid.zarr/lat_v/0.0 +0 -0
  167. roms_tools/tests/test_setup/test_data/grid.zarr/pm/0.0 +0 -0
  168. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zattrs +1 -1
  169. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/.zmetadata +1 -1
  170. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/angle/0.0 +0 -0
  171. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/angle_coarse/0.0 +0 -0
  172. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/f/0.0 +0 -0
  173. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/h/0.0 +0 -0
  174. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_coarse/0.0 +0 -0
  175. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_rho/0.0 +0 -0
  176. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_u/0.0 +0 -0
  177. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lat_v/0.0 +0 -0
  178. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_coarse/0.0 +0 -0
  179. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_rho/0.0 +0 -0
  180. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_u/0.0 +0 -0
  181. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/lon_v/0.0 +0 -0
  182. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/pm/0.0 +0 -0
  183. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/pn/0.0 +0 -0
  184. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zattrs +1 -1
  185. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/.zmetadata +1 -1
  186. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/salt/0.0.0.0 +0 -0
  187. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/temp/0.0.0.0 +0 -0
  188. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/u/0.0.0.0 +0 -0
  189. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ubar/0.0.0 +0 -0
  190. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/v/0.0.0.0 +0 -0
  191. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/vbar/0.0.0 +0 -0
  192. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zeta/0.0.0 +0 -0
  193. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zmetadata +27 -1
  194. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/nriver/.zarray +20 -0
  195. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/nriver/.zattrs +6 -0
  196. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/nriver/0 +0 -0
  197. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_location/.zattrs +1 -1
  198. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/.zmetadata +27 -1
  199. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/nriver/.zarray +20 -0
  200. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/nriver/.zattrs +6 -0
  201. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/nriver/0 +0 -0
  202. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_location/.zattrs +1 -1
  203. roms_tools/tests/test_setup/test_initial_conditions.py +16 -0
  204. roms_tools/tests/test_setup/test_nesting.py +141 -104
  205. roms_tools/tests/test_setup/test_river_forcing.py +580 -266
  206. roms_tools/tests/test_setup/test_surface_forcing.py +47 -0
  207. roms_tools/tests/test_setup/test_validation.py +34 -2
  208. roms_tools/utils.py +11 -7
  209. roms_tools/vertical_coordinate.py +1 -0
  210. {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info}/METADATA +22 -11
  211. {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info}/RECORD +214 -206
  212. {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info}/WHEEL +1 -1
  213. {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info/licenses}/LICENSE +0 -0
  214. {roms_tools-2.4.0.dist-info → roms_tools-2.6.0.dist-info}/top_level.txt +0 -0
@@ -8,7 +8,7 @@ from pathlib import Path
8
8
  import logging
9
9
  from datetime import datetime
10
10
  from roms_tools import Grid
11
- from roms_tools.regrid import LateralRegrid, VerticalRegrid
11
+ from roms_tools.regrid import LateralRegridToROMS, VerticalRegridToROMS
12
12
  from roms_tools.plot import _plot, _section_plot, _profile_plot, _line_plot
13
13
  from roms_tools.utils import (
14
14
  transpose_dimensions,
@@ -34,7 +34,7 @@ from roms_tools.setup.utils import (
34
34
  )
35
35
 
36
36
 
37
- @dataclass(frozen=True, kw_only=True)
37
+ @dataclass(kw_only=True)
38
38
  class InitialConditions:
39
39
  """Represents initial conditions for ROMS, including physical and biogeochemical
40
40
  data.
@@ -115,7 +115,7 @@ class InitialConditions:
115
115
 
116
116
  self._input_checks()
117
117
  # Dataset for depth coordinates
118
- object.__setattr__(self, "ds_depth_coords", xr.Dataset())
118
+ self.ds_depth_coords = xr.Dataset()
119
119
 
120
120
  processed_fields = {}
121
121
  processed_fields = self._process_data(processed_fields, type="physics")
@@ -135,7 +135,7 @@ class InitialConditions:
135
135
  for var_name in ds.data_vars:
136
136
  ds[var_name] = substitute_nans_by_fillvalue(ds[var_name])
137
137
 
138
- object.__setattr__(self, "ds", ds)
138
+ self.ds = ds
139
139
 
140
140
  def _process_data(self, processed_fields, type="physics"):
141
141
 
@@ -150,6 +150,8 @@ class InitialConditions:
150
150
  target_coords,
151
151
  buffer_points=20, # lateral fill needs good buffer from data margin
152
152
  )
153
+ # Enforce double precision to ensure reproducibility
154
+ data.convert_to_float64()
153
155
  data.extrapolate_deepest_to_bottom()
154
156
  data.apply_lateral_fill()
155
157
 
@@ -159,7 +161,7 @@ class InitialConditions:
159
161
  var_names = variable_info.keys()
160
162
 
161
163
  # lateral regridding
162
- lateral_regrid = LateralRegrid(target_coords, data.dim_names)
164
+ lateral_regrid = LateralRegridToROMS(target_coords, data.dim_names)
163
165
 
164
166
  for var_name in var_names:
165
167
  if var_name in data.var_names.keys():
@@ -204,7 +206,7 @@ class InitialConditions:
204
206
  # Vertical regridding
205
207
  for location in ["rho", "u", "v"]:
206
208
  if len(var_names_dict[location]) > 0:
207
- vertical_regrid = VerticalRegrid(
209
+ vertical_regrid = VerticalRegridToROMS(
208
210
  self.ds_depth_coords[f"layer_depth_{location}"],
209
211
  data.ds[data.dim_names["depth"]],
210
212
  )
@@ -234,20 +236,21 @@ class InitialConditions:
234
236
  return processed_fields
235
237
 
236
238
  def _input_checks(self):
239
+ # Check that ini_time is not None
240
+ if self.ini_time is None:
241
+ raise ValueError(
242
+ "`ini_time` must be a valid datetime object and cannot be None."
243
+ )
237
244
 
238
245
  if "name" not in self.source.keys():
239
246
  raise ValueError("`source` must include a 'name'.")
240
247
  if "path" not in self.source.keys():
241
248
  raise ValueError("`source` must include a 'path'.")
242
249
  # set self.source["climatology"] to False if not provided
243
- object.__setattr__(
244
- self,
245
- "source",
246
- {
247
- **self.source,
248
- "climatology": self.source.get("climatology", False),
249
- },
250
- )
250
+ self.source = {
251
+ **self.source,
252
+ "climatology": self.source.get("climatology", False),
253
+ }
251
254
  if self.bgc_source is not None:
252
255
  if "name" not in self.bgc_source.keys():
253
256
  raise ValueError(
@@ -258,14 +261,10 @@ class InitialConditions:
258
261
  "`bgc_source` must include a 'path' if it is provided."
259
262
  )
260
263
  # set self.bgc_source["climatology"] to False if not provided
261
- object.__setattr__(
262
- self,
263
- "bgc_source",
264
- {
265
- **self.bgc_source,
266
- "climatology": self.bgc_source.get("climatology", False),
267
- },
268
- )
264
+ self.bgc_source = {
265
+ **self.bgc_source,
266
+ "climatology": self.bgc_source.get("climatology", False),
267
+ }
269
268
  if self.adjust_depth_for_sea_surface_height:
270
269
  logging.info("Sea surface height will be used to adjust depth coordinates.")
271
270
  else:
@@ -648,7 +647,7 @@ class InitialConditions:
648
647
  visualize the layering of the water column. For clarity, the number of layer
649
648
  contours displayed is limited to a maximum of 10. Default is False.
650
649
  ax : matplotlib.axes.Axes, optional
651
- The axes to plot on. If None, a new figure is created. Note that this argument does not work for horizontal plots that display the eta- and xi-dimensions at the same time.
650
+ The axes to plot on. If None, a new figure is created. Note that this argument does not work for 2D horizontal plots. Default is None.
652
651
 
653
652
  Returns
654
653
  -------
@@ -680,13 +679,6 @@ class InitialConditions:
680
679
  "Conflicting input: For 2D fields, specify only one dimension, either 'eta' or 'xi', not both."
681
680
  )
682
681
 
683
- # Load the data
684
- if self.use_dask:
685
- from dask.diagnostics import ProgressBar
686
-
687
- with ProgressBar():
688
- self.ds[var_name].load()
689
-
690
682
  field = self.ds[var_name].squeeze()
691
683
 
692
684
  # Get correct mask and horizontal coordinates
@@ -708,11 +700,18 @@ class InitialConditions:
708
700
 
709
701
  field = field.assign_coords({"lon": lon_deg, "lat": lat_deg})
710
702
 
703
+ # Load the data
704
+ if self.use_dask:
705
+ from dask.diagnostics import ProgressBar
706
+
707
+ with ProgressBar():
708
+ self.ds[var_name].load()
709
+
711
710
  # Retrieve depth coordinates
712
711
  if s is not None:
713
712
  layer_contours = False
714
713
  # Note that `layer_depth_{loc}` has already been computed during `__post_init__`.
715
- layer_depth = self.ds_depth_coords[f"layer_depth_{loc}"].squeeze()
714
+ layer_depth = self.ds_depth_coords[f"layer_depth_{loc}"].squeeze().load()
716
715
 
717
716
  # Slice the field as desired
718
717
  def _slice_and_assign(
@@ -898,7 +897,6 @@ class InitialConditions:
898
897
  cls,
899
898
  filepath: Union[str, Path],
900
899
  use_dask: bool = False,
901
- bypass_validation: bool = False,
902
900
  ) -> "InitialConditions":
903
901
  """Create an instance of the InitialConditions class from a YAML file.
904
902
 
@@ -908,10 +906,6 @@ class InitialConditions:
908
906
  The path to the YAML file from which the parameters will be read.
909
907
  use_dask: bool, optional
910
908
  Indicates whether to use dask for processing. If True, data is processed with dask; if False, data is processed eagerly. Defaults to False.
911
- bypass_validation: bool, optional
912
- Indicates whether to skip validation checks in the processed data. When set to True,
913
- the validation process that ensures no NaN values exist at wet points
914
- in the processed dataset is bypassed. Defaults to False.
915
909
 
916
910
  Returns
917
911
  -------
@@ -926,5 +920,4 @@ class InitialConditions:
926
920
  grid=grid,
927
921
  **initial_conditions_params,
928
922
  use_dask=use_dask,
929
- bypass_validation=bypass_validation,
930
923
  )
@@ -2,13 +2,14 @@ import numpy as np
2
2
  import xarray as xr
3
3
  from scipy.interpolate import griddata
4
4
  from dataclasses import dataclass, field
5
- from typing import Dict, Union
5
+ from typing import Dict, Union, Any, Tuple
6
6
  from pathlib import Path
7
7
  import logging
8
8
  from scipy.interpolate import interp1d
9
9
  from roms_tools import Grid
10
10
  from roms_tools.plot import _plot_nesting
11
11
  from roms_tools.utils import save_datasets
12
+ from roms_tools.setup.topography import _clip_depth
12
13
  from roms_tools.setup.utils import (
13
14
  interpolate_from_rho_to_u,
14
15
  interpolate_from_rho_to_v,
@@ -19,40 +20,41 @@ from roms_tools.setup.utils import (
19
20
  )
20
21
 
21
22
 
22
- @dataclass(frozen=True, kw_only=True)
23
- class Nesting:
24
- """Represents the relationship between a parent and a child grid in nested ROMS
25
- simulations. This class facilitates mapping the boundaries of the child grid onto
26
- the parent grid indices and modifying the child grid topography such that it matches
27
- the parent topography at the boundaries.
23
+ @dataclass(kw_only=True)
24
+ class ChildGrid(Grid):
25
+ """Represents a ROMS child grid that is compatible with the provided parent grid.
26
+
27
+ This class establishes the relationship between a parent grid and a child grid in ROMS simulations.
28
+ It generates two datasets:
29
+
30
+ 1. `ds`: Contains child grid variables, ensuring compatibility with the parent grid.
31
+ The child grid’s topography and mask are adjusted to match the parent grid at the boundaries.
32
+
33
+ 2. `ds_nesting`: Contains boundary mappings, linking the child grid’s boundaries
34
+ to the corresponding parent grid indices.
28
35
 
29
36
  Parameters
30
37
  ----------
31
38
  parent_grid : Grid
32
- The parent grid object, containing information about the larger domain.
33
- child_grid : Grid
34
- The child grid object, containing information about the nested domain.
35
- boundaries : Dict[str, bool], optional
36
- Dictionary specifying which boundaries of the child grid are used
37
- in the nesting process. Keys are "south", "east", "north", and "west",
38
- with boolean values indicating inclusion. Defaults to all boundaries (True).
39
- child_prefix : str, optional
40
- Prefix added to variable names in the generated dataset to distinguish
41
- child grid information. Defaults to "child".
42
- period : float, optional
43
- The temporal resolution or output period for boundary variables in the child grid.
44
- Defaults to hourly.
39
+ The parent grid object, providing the reference for the child grid's topography and mask.
40
+ boundaries : Dict[str, bool]
41
+ Specifies which child grid boundaries (south, east, north, west) should be adjusted for topography/mask
42
+ and included in `ds_nesting`. Defaults to all `True`.
43
+ metadata : Dict[str, Any]
44
+ Dictionary configuring the boundary nesting process, including:
45
+
46
+ - `"prefix"` (str): Prefix for variable names in `ds_nesting`. Defaults to `"child"`.
47
+ - `"period"` (float): Temporal resolution for boundary outputs in seconds. Defaults to 3600 (hourly).
45
48
 
46
49
  Attributes
47
50
  ----------
48
51
  ds : xr.Dataset
49
- An xarray Dataset containing the index mappings between the child and parent grids
50
- for each specified boundary. Includes metadata about grid points, angles,
51
- and boundary variable outputs.
52
+ Dataset containing child grid variables aligned with the parent grid’s topography and mask at the boundaries.
53
+ ds_nesting : xr.Dataset
54
+ Dataset containing boundary mappings, where child grid boundaries are mapped onto parent grid indices.
52
55
  """
53
56
 
54
57
  parent_grid: Grid
55
- child_grid: Grid
56
58
  boundaries: Dict[str, bool] = field(
57
59
  default_factory=lambda: {
58
60
  "south": True,
@@ -61,40 +63,96 @@ class Nesting:
61
63
  "west": True,
62
64
  }
63
65
  )
64
- child_prefix: str = "child"
65
- period: float = 3600.0
66
+ metadata: Dict[str, Any] = field(
67
+ default_factory=lambda: {"prefix": "child", "period": 3600.0}
68
+ )
66
69
 
67
70
  def __post_init__(self):
68
71
 
69
- parent_grid_ds = self.parent_grid.ds
70
- child_grid_ds = self.child_grid.ds
72
+ super().__post_init__()
73
+ self._map_child_boundaries_onto_parent_grid_indices()
74
+ self._modify_child_topography_and_mask()
71
75
 
72
- # Adjust longitude for dateline crossing to prevent interpolation artifacts
73
- for grid_ds in [parent_grid_ds, child_grid_ds]:
74
- grid_ds = wrap_longitudes(grid_ds, straddle=self.parent_grid.straddle)
76
+ def _map_child_boundaries_onto_parent_grid_indices(self):
77
+ """Maps child grid boundary points onto absolute indices of the parent grid."""
78
+ # Prepare parent and child grid datasets by adjusting longitudes for dateline crossing
79
+ parent_grid_ds, child_grid_ds = self._prepare_grid_datasets()
75
80
 
76
81
  # Map child boundaries onto parent grid indices
77
- ds = map_child_boundaries_onto_parent_grid_indices(
82
+ ds_nesting = map_child_boundaries_onto_parent_grid_indices(
78
83
  parent_grid_ds,
79
84
  child_grid_ds,
80
85
  self.boundaries,
81
- self.child_prefix,
82
- self.period,
86
+ self.metadata["prefix"],
87
+ self.metadata["period"],
83
88
  )
84
- object.__setattr__(self, "ds", ds)
85
89
 
86
- # Modify child topography and mask to match the parent grid
90
+ self.ds_nesting = ds_nesting
91
+
92
+ def _modify_child_topography_and_mask(self):
93
+ """Adjust the child grid's topography and mask to align with the parent grid.
94
+
95
+ Uses a weighted sum based on boundary distance and clips depth values to a
96
+ minimum.
97
+ """
98
+ # Prepare parent and child grid datasets by adjusting longitudes for dateline crossing
99
+ parent_grid_ds, child_grid_ds = self._prepare_grid_datasets()
100
+
87
101
  child_grid_ds = modify_child_topography_and_mask(
88
- parent_grid_ds, child_grid_ds, self.boundaries
102
+ parent_grid_ds, child_grid_ds, self.boundaries, self.hmin
103
+ )
104
+
105
+ # Finalize grid datasets by adjusting longitudes back to [0, 360] range
106
+ parent_grid_ds, child_grid_ds = self._finalize_grid_datasets(
107
+ parent_grid_ds, child_grid_ds
108
+ )
109
+
110
+ self.ds = child_grid_ds
111
+
112
+ def update_topography(
113
+ self, topography_source=None, hmin=None, verbose=False
114
+ ) -> None:
115
+
116
+ """Update the child grid topography via the following steps:
117
+
118
+ - Regrids the topography based on the specified source.
119
+ - Applies global and local smoothing.
120
+ - Adjusts the child grid topography and mask to match the parent grid.
121
+ - Ensures the minimum depth constraint (`hmin`) is enforced.
122
+ - Updates the internal dataset (`self.ds`) with the processed topography.
123
+
124
+ Parameters
125
+ ----------
126
+ topography_source : dict, optional
127
+ A dictionary specifying the source of the topography data. Expected keys:
128
+ - `"name"` (str): Name of the topography dataset (e.g., `"SRTM15"`).
129
+ - `"path"` (str or Path): File path to the topography dataset.
130
+
131
+ If not provided, the existing topography source remains unchanged.
132
+
133
+ hmin : float, optional
134
+ The minimum allowable ocean depth (in meters). If not provided, the existing
135
+ value remains unchanged.
136
+
137
+ verbose : bool, optional
138
+ If `True`, prints detailed information about each processing step, including
139
+ timing and modifications. Defaults to `False`.
140
+
141
+ Returns
142
+ -------
143
+ None
144
+ This method updates the internal dataset (`self.ds`) in place, modifying the
145
+ topography variable. It does not return a value.
146
+ """
147
+
148
+ super().update_topography(
149
+ topography_source=topography_source, hmin=hmin, verbose=verbose
89
150
  )
90
151
 
91
- # Convert longitudes back to [0, 360] range
92
- for grid_ds in [parent_grid_ds, child_grid_ds]:
93
- grid_ds = wrap_longitudes(grid_ds, straddle=False)
94
- object.__setattr__(self.parent_grid, "ds", parent_grid_ds)
95
- object.__setattr__(self.child_grid, "ds", child_grid_ds)
152
+ # Modify child topography and mask to match the parent grid
153
+ self._modify_child_topography_and_mask()
96
154
 
97
- def plot(self, with_dim_names=False) -> None:
155
+ def plot_nesting(self, with_dim_names=False) -> None:
98
156
  """Plot the parent and child grids in a single figure.
99
157
 
100
158
  Returns
@@ -105,27 +163,22 @@ class Nesting:
105
163
 
106
164
  _plot_nesting(
107
165
  self.parent_grid.ds,
108
- self.child_grid.ds,
166
+ self.ds,
109
167
  self.parent_grid.straddle,
110
168
  with_dim_names,
111
169
  )
112
170
 
113
- def save(
171
+ def save_nesting(
114
172
  self,
115
173
  filepath: Union[str, Path],
116
- filepath_child_grid: Union[str, Path],
117
174
  ) -> None:
118
- """Save the nesting and child grid file to netCDF4 files. The child grid file is
119
- required because the topography and mask of the child grid has been modified.
175
+ """Save the nesting information to netCDF4 files.
120
176
 
121
177
  Parameters
122
178
  ----------
123
179
  filepath : Union[str, Path]
124
180
  The base path and filename for the output files. The filenames will include the specified path and the `.nc` extension.
125
181
 
126
- filepath_child_grid : Union[str, Path]
127
- The base path and filename for saving the childe grid file.
128
-
129
182
  Returns
130
183
  -------
131
184
  List[Path]
@@ -134,16 +187,13 @@ class Nesting:
134
187
 
135
188
  # Ensure filepath is a Path object
136
189
  filepath = Path(filepath)
137
- filepath_child_grid = Path(filepath_child_grid)
138
190
 
139
191
  # Remove ".nc" suffix if present
140
192
  if filepath.suffix == ".nc":
141
193
  filepath = filepath.with_suffix("")
142
- if filepath_child_grid.suffix == ".nc":
143
- filepath_child_grid = filepath_child_grid.with_suffix("")
144
194
 
145
- dataset_list = [self.ds, self.child_grid.ds]
146
- output_filenames = [str(filepath), str(filepath_child_grid)]
195
+ dataset_list = [self.ds_nesting]
196
+ output_filenames = [str(filepath)]
147
197
 
148
198
  saved_filenames = save_datasets(dataset_list, output_filenames)
149
199
 
@@ -162,8 +212,8 @@ class Nesting:
162
212
  _to_yaml(self, filepath)
163
213
 
164
214
  @classmethod
165
- def from_yaml(cls, filepath: Union[str, Path]) -> "Nesting":
166
- """Create an instance of the Nesting class from a YAML file.
215
+ def from_yaml(cls, filepath: Union[str, Path]) -> "ChildGrid":
216
+ """Create an instance of the ChildGrid class from a YAML file.
167
217
 
168
218
  Parameters
169
219
  ----------
@@ -173,25 +223,115 @@ class Nesting:
173
223
  Returns
174
224
  -------
175
225
  Nesting
176
- An instance of the Nesting class.
226
+ An instance of the ChildGrid class.
177
227
  """
178
228
  filepath = Path(filepath)
179
229
 
180
230
  parent_grid = Grid.from_yaml(filepath, "ParentGrid")
181
- child_grid = Grid.from_yaml(filepath, "ChildGrid")
182
231
  params = _from_yaml(cls, filepath)
183
232
 
184
- return cls(parent_grid=parent_grid, child_grid=child_grid, **params)
233
+ return cls(parent_grid=parent_grid, **params)
234
+
235
+ def _prepare_grid_datasets(self) -> Tuple[xr.Dataset, xr.Dataset]:
236
+ """Prepare parent and child grid datasets by adjusting longitudes for dateline
237
+ crossing.
238
+
239
+ This method ensures that longitudes are properly wrapped to avoid interpolation artifacts
240
+ and returns the updated parent and child grid datasets.
241
+
242
+ Returns
243
+ -------
244
+ Tuple[xr.Dataset, xr.Dataset]
245
+ A tuple containing:
246
+ - The modified parent grid dataset.
247
+ - The modified child grid dataset.
248
+ """
249
+ parent_grid_ds = wrap_longitudes(
250
+ self.parent_grid.ds, straddle=self.parent_grid.straddle
251
+ )
252
+ child_grid_ds = wrap_longitudes(self.ds, straddle=self.parent_grid.straddle)
253
+ return parent_grid_ds, child_grid_ds
254
+
255
+ def _finalize_grid_datasets(
256
+ self, parent_grid_ds: xr.Dataset, child_grid_ds: xr.Dataset
257
+ ) -> None:
258
+ """Finalize the grid datasets by converting longitudes back to the [0, 360]
259
+ range.
260
+
261
+ Parameters
262
+ ----------
263
+ parent_grid_ds : xr.Dataset
264
+ The parent grid dataset after modifications.
265
+
266
+ child_grid_ds : xr.Dataset
267
+ The child grid dataset after modifications.
268
+ """
269
+ parent_grid_ds = wrap_longitudes(parent_grid_ds, straddle=False)
270
+ child_grid_ds = wrap_longitudes(child_grid_ds, straddle=False)
271
+ return parent_grid_ds, child_grid_ds
272
+
273
+ @classmethod
274
+ def from_file(
275
+ cls, filepath: Union[str, Path], verbose: bool = False
276
+ ) -> "ChildGrid":
277
+ """This method is disabled in this subclass.
278
+
279
+ .. noindex::
280
+ """
281
+ raise NotImplementedError(
282
+ "The 'from_file' method is disabled in this subclass."
283
+ )
185
284
 
186
285
 
187
286
  def map_child_boundaries_onto_parent_grid_indices(
188
287
  parent_grid_ds,
189
288
  child_grid_ds,
190
289
  boundaries={"south": True, "east": True, "north": True, "west": True},
191
- child_prefix="child",
290
+ prefix="child",
192
291
  period=3600.0,
193
292
  update_land_indices=True,
194
293
  ):
294
+ """Maps child grid boundary points onto absolute indices of the parent grid.
295
+
296
+ This function interpolates the spatial indices of the child grid boundaries onto
297
+ the parent grid, ensuring alignment between the two grids. It supports all four
298
+ boundaries (south, east, north, and west) and considers different grid locations
299
+ (`rho`, `u`, and `v`). Additionally, it updates land indices if they fall onto
300
+ land points in the parent grid.
301
+
302
+ Parameters
303
+ ----------
304
+ parent_grid_ds : xarray.Dataset
305
+ The parent grid dataset containing longitude, latitude, and mask variables.
306
+
307
+ child_grid_ds : xarray.Dataset
308
+ The child grid dataset containing longitude, latitude, mask, and angle variables.
309
+
310
+ boundaries : dict, optional
311
+ A dictionary specifying which child boundaries should be mapped onto the parent grid.
312
+ Keys should be `"south"`, `"east"`, `"north"`, and `"west"`, with boolean values
313
+ indicating whether to process each boundary. Defaults to mapping all boundaries.
314
+
315
+ prefix : str, optional
316
+ A string prefix for naming the output variables in the resulting dataset.
317
+ Defaults to `"child"`.
318
+
319
+ period : float, optional
320
+ The output period (in seconds) to be assigned to the mapped boundary indices.
321
+ Defaults to `3600.0` (1 hour).
322
+
323
+ update_land_indices : bool, optional
324
+ If `True`, updates indices that fall on land in the parent grid to nearby ocean points.
325
+ Defaults to `True`.
326
+
327
+ Returns
328
+ -------
329
+ xarray.Dataset
330
+ A dataset containing the mapped boundary indices for `rho`, `u`, and `v` grid points.
331
+ - For `rho` points: Contains mapped `xi` and `eta` indices.
332
+ - For `u` and `v` points: Contains mapped `xi`, `eta`, and angle values.
333
+ - Attributes include long names, output variable names, units, and output period.
334
+ """
195
335
 
196
336
  bdry_coords_dict = get_boundary_coords()
197
337
 
@@ -234,7 +374,7 @@ def map_child_boundaries_onto_parent_grid_indices(
234
374
  i_eta, i_xi, grid_location, parent_grid_ds
235
375
  )
236
376
 
237
- var_name = f"{child_prefix}_{direction}_{suffix}"
377
+ var_name = f"{prefix}_{direction}_{suffix}"
238
378
  if grid_location == "rho":
239
379
  ds[var_name] = xr.concat([i_xi, i_eta], dim="two")
240
380
  ds[var_name].attrs[
@@ -265,7 +405,7 @@ def map_child_boundaries_onto_parent_grid_indices(
265
405
 
266
406
  # Rename dimensions
267
407
  dims_to_rename = {
268
- dim: f"{child_prefix}_{dim}" for dim in ds.dims if dim not in ["two", "three"]
408
+ dim: f"{prefix}_{dim}" for dim in ds.dims if dim not in ["two", "three"]
269
409
  }
270
410
  ds = ds.rename(dims_to_rename)
271
411
 
@@ -445,7 +585,39 @@ def modify_child_topography_and_mask(
445
585
  parent_grid_ds,
446
586
  child_grid_ds,
447
587
  boundaries={"south": True, "east": True, "north": True, "west": True},
588
+ hmin=5.0,
448
589
  ):
590
+ """Adjust the child grid topography and mask to align with the parent grid.
591
+
592
+ The child grid's topography is adjusted using a weighted sum based on the boundary distance,
593
+ and the depth values are clipped to enforce a minimum depth constraint.
594
+
595
+ Parameters
596
+ ----------
597
+ parent_grid_ds : xarray.Dataset
598
+ The parent grid dataset containing `h` (topography) and `mask_rho` (land-sea mask).
599
+
600
+ child_grid_ds : xarray.Dataset
601
+ The child grid dataset whose `h` and `mask_rho` will be modified.
602
+
603
+ boundaries : dict, optional
604
+ A dictionary specifying which boundaries should be modified. Expected keys:
605
+ - `"south"` (bool): Whether to adjust the southern boundary.
606
+ - `"east"` (bool): Whether to adjust the eastern boundary.
607
+ - `"north"` (bool): Whether to adjust the northern boundary.
608
+ - `"west"` (bool): Whether to adjust the western boundary.
609
+ Defaults to modifying all boundaries.
610
+
611
+ hmin : float, optional
612
+ The minimum allowable ocean depth (in meters). Depth values in the modified
613
+ child topography will be clipped to ensure they meet or exceed this value.
614
+ Defaults to `5.0` meters.
615
+
616
+ Returns
617
+ -------
618
+ xarray.Dataset
619
+ The updated child grid dataset with modified topography (`h`) and mask (`mask_rho`).
620
+ """
449
621
 
450
622
  # regrid parent topography and mask onto child grid
451
623
  points = np.column_stack(
@@ -471,6 +643,8 @@ def modify_child_topography_and_mask(
471
643
  child_grid_ds["h"] = (
472
644
  alpha * child_grid_ds["h"] + (1 - alpha) * h_parent_interpolated
473
645
  )
646
+ # Clip depth on modified child topography
647
+ child_grid_ds["h"] = _clip_depth(child_grid_ds["h"], hmin)
474
648
 
475
649
  child_mask = (
476
650
  alpha * child_grid_ds["mask_rho"] + (1 - alpha) * mask_parent_interpolated