roms-tools 2.6.1__py3-none-any.whl → 2.7.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 (646) hide show
  1. roms_tools/__init__.py +1 -0
  2. roms_tools/analysis/roms_output.py +11 -77
  3. roms_tools/analysis/utils.py +0 -66
  4. roms_tools/constants.py +2 -0
  5. roms_tools/download.py +47 -3
  6. roms_tools/plot.py +22 -5
  7. roms_tools/setup/boundary_forcing.py +92 -70
  8. roms_tools/setup/cdr_forcing.py +1126 -0
  9. roms_tools/setup/datasets.py +952 -337
  10. roms_tools/setup/grid.py +42 -4
  11. roms_tools/setup/initial_conditions.py +70 -34
  12. roms_tools/setup/river_forcing.py +31 -98
  13. roms_tools/setup/surface_forcing.py +19 -3
  14. roms_tools/setup/tides.py +81 -411
  15. roms_tools/setup/utils.py +460 -75
  16. roms_tools/tests/test_setup/test_boundary_forcing.py +119 -36
  17. roms_tools/tests/test_setup/test_cdr_forcing.py +772 -0
  18. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/.zattrs +14 -0
  19. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/.zgroup +3 -0
  20. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/.zmetadata +4456 -0
  21. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_east/.zarray +24 -0
  22. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_east/.zattrs +10 -0
  23. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_east/0.0.0 +0 -0
  24. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_north/.zarray +24 -0
  25. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_north/.zattrs +10 -0
  26. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_north/0.0.0 +0 -0
  27. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_south/.zarray +24 -0
  28. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_south/.zattrs +10 -0
  29. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_south/0.0.0 +0 -0
  30. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_west/.zarray +24 -0
  31. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_west/.zattrs +10 -0
  32. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_west/0.0.0 +0 -0
  33. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_east/.zarray +24 -0
  34. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_east/.zattrs +10 -0
  35. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_east/0.0.0 +0 -0
  36. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_north/.zarray +24 -0
  37. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_north/.zattrs +10 -0
  38. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_north/0.0.0 +0 -0
  39. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_south/.zarray +24 -0
  40. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_south/.zattrs +10 -0
  41. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_south/0.0.0 +0 -0
  42. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_west/.zarray +24 -0
  43. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_west/.zattrs +10 -0
  44. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_west/0.0.0 +0 -0
  45. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_east/.zarray +24 -0
  46. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_east/.zattrs +10 -0
  47. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_east/0.0.0 +0 -0
  48. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_north/.zarray +24 -0
  49. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_north/.zattrs +10 -0
  50. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_north/0.0.0 +0 -0
  51. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_south/.zarray +24 -0
  52. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_south/.zattrs +10 -0
  53. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_south/0.0.0 +0 -0
  54. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_west/.zarray +24 -0
  55. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_west/.zattrs +10 -0
  56. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_west/0.0.0 +0 -0
  57. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_east/.zarray +24 -0
  58. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_east/.zattrs +10 -0
  59. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_east/0.0.0 +0 -0
  60. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_north/.zarray +24 -0
  61. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_north/.zattrs +10 -0
  62. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_north/0.0.0 +0 -0
  63. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_south/.zarray +24 -0
  64. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_south/.zattrs +10 -0
  65. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_south/0.0.0 +0 -0
  66. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_west/.zarray +24 -0
  67. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_west/.zattrs +10 -0
  68. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_west/0.0.0 +0 -0
  69. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_east/.zarray +24 -0
  70. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_east/.zattrs +10 -0
  71. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_east/0.0.0 +0 -0
  72. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_north/.zarray +24 -0
  73. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_north/.zattrs +10 -0
  74. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_north/0.0.0 +0 -0
  75. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_south/.zarray +24 -0
  76. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_south/.zattrs +10 -0
  77. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_south/0.0.0 +0 -0
  78. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_west/.zarray +24 -0
  79. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_west/.zattrs +10 -0
  80. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_west/0.0.0 +0 -0
  81. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_east/.zarray +24 -0
  82. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_east/.zattrs +10 -0
  83. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_east/0.0.0 +0 -0
  84. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_north/.zarray +24 -0
  85. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_north/.zattrs +10 -0
  86. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_north/0.0.0 +0 -0
  87. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_south/.zarray +24 -0
  88. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_south/.zattrs +10 -0
  89. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_south/0.0.0 +0 -0
  90. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_west/.zarray +24 -0
  91. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_west/.zattrs +10 -0
  92. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_west/0.0.0 +0 -0
  93. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_east/.zarray +24 -0
  94. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_east/.zattrs +10 -0
  95. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_east/0.0.0 +0 -0
  96. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_north/.zarray +24 -0
  97. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_north/.zattrs +10 -0
  98. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_north/0.0.0 +0 -0
  99. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_south/.zarray +24 -0
  100. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_south/.zattrs +10 -0
  101. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_south/0.0.0 +0 -0
  102. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_west/.zarray +24 -0
  103. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_west/.zattrs +10 -0
  104. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_west/0.0.0 +0 -0
  105. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_east/.zarray +24 -0
  106. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_east/.zattrs +10 -0
  107. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_east/0.0.0 +0 -0
  108. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_north/.zarray +24 -0
  109. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_north/.zattrs +10 -0
  110. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_north/0.0.0 +0 -0
  111. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_south/.zarray +24 -0
  112. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_south/.zattrs +10 -0
  113. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_south/0.0.0 +0 -0
  114. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_west/.zarray +24 -0
  115. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_west/.zattrs +10 -0
  116. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_west/0.0.0 +0 -0
  117. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_east/.zarray +24 -0
  118. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_east/.zattrs +10 -0
  119. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_east/0.0.0 +0 -0
  120. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_north/.zarray +24 -0
  121. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_north/.zattrs +10 -0
  122. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_north/0.0.0 +0 -0
  123. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_south/.zarray +24 -0
  124. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_south/.zattrs +10 -0
  125. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_south/0.0.0 +0 -0
  126. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_west/.zarray +24 -0
  127. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_west/.zattrs +10 -0
  128. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_west/0.0.0 +0 -0
  129. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_east/.zarray +24 -0
  130. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_east/.zattrs +10 -0
  131. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_east/0.0.0 +0 -0
  132. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_north/.zarray +24 -0
  133. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_north/.zattrs +10 -0
  134. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_north/0.0.0 +0 -0
  135. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_south/.zarray +24 -0
  136. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_south/.zattrs +10 -0
  137. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_south/0.0.0 +0 -0
  138. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_west/.zarray +24 -0
  139. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_west/.zattrs +10 -0
  140. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_west/0.0.0 +0 -0
  141. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_east/.zarray +24 -0
  142. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_east/.zattrs +10 -0
  143. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_east/0.0.0 +0 -0
  144. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_north/.zarray +24 -0
  145. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_north/.zattrs +10 -0
  146. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_north/0.0.0 +0 -0
  147. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_south/.zarray +24 -0
  148. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_south/.zattrs +10 -0
  149. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_south/0.0.0 +0 -0
  150. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_west/.zarray +24 -0
  151. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_west/.zattrs +10 -0
  152. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_west/0.0.0 +0 -0
  153. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_east/.zarray +24 -0
  154. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_east/.zattrs +10 -0
  155. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_east/0.0.0 +0 -0
  156. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_north/.zarray +24 -0
  157. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_north/.zattrs +10 -0
  158. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_north/0.0.0 +0 -0
  159. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_south/.zarray +24 -0
  160. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_south/.zattrs +10 -0
  161. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_south/0.0.0 +0 -0
  162. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_west/.zarray +24 -0
  163. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_west/.zattrs +10 -0
  164. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_west/0.0.0 +0 -0
  165. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_east/.zarray +24 -0
  166. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_east/.zattrs +10 -0
  167. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_east/0.0.0 +0 -0
  168. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_north/.zarray +24 -0
  169. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_north/.zattrs +10 -0
  170. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_north/0.0.0 +0 -0
  171. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_south/.zarray +24 -0
  172. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_south/.zattrs +10 -0
  173. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_south/0.0.0 +0 -0
  174. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_west/.zarray +24 -0
  175. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_west/.zattrs +10 -0
  176. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_west/0.0.0 +0 -0
  177. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_east/.zarray +24 -0
  178. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_east/.zattrs +10 -0
  179. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_east/0.0.0 +0 -0
  180. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_north/.zarray +24 -0
  181. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_north/.zattrs +10 -0
  182. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_north/0.0.0 +0 -0
  183. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_south/.zarray +24 -0
  184. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_south/.zattrs +10 -0
  185. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_south/0.0.0 +0 -0
  186. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_west/.zarray +24 -0
  187. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_west/.zattrs +10 -0
  188. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_west/0.0.0 +0 -0
  189. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_east/.zarray +24 -0
  190. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_east/.zattrs +10 -0
  191. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_east/0.0.0 +0 -0
  192. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_north/.zarray +24 -0
  193. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_north/.zattrs +10 -0
  194. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_north/0.0.0 +0 -0
  195. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_south/.zarray +24 -0
  196. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_south/.zattrs +10 -0
  197. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_south/0.0.0 +0 -0
  198. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_west/.zarray +24 -0
  199. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_west/.zattrs +10 -0
  200. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_west/0.0.0 +0 -0
  201. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_east/.zarray +24 -0
  202. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_east/.zattrs +10 -0
  203. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_east/0.0.0 +0 -0
  204. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_north/.zarray +24 -0
  205. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_north/.zattrs +10 -0
  206. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_north/0.0.0 +0 -0
  207. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_south/.zarray +24 -0
  208. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_south/.zattrs +10 -0
  209. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_south/0.0.0 +0 -0
  210. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_west/.zarray +24 -0
  211. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_west/.zattrs +10 -0
  212. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_west/0.0.0 +0 -0
  213. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_east/.zarray +24 -0
  214. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_east/.zattrs +10 -0
  215. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_east/0.0.0 +0 -0
  216. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_north/.zarray +24 -0
  217. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_north/.zattrs +10 -0
  218. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_north/0.0.0 +0 -0
  219. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_south/.zarray +24 -0
  220. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_south/.zattrs +10 -0
  221. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_south/0.0.0 +0 -0
  222. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_west/.zarray +24 -0
  223. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_west/.zattrs +10 -0
  224. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_west/0.0.0 +0 -0
  225. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/abs_time/.zarray +20 -0
  226. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/abs_time/.zattrs +8 -0
  227. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/abs_time/0 +0 -0
  228. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/bry_time/.zarray +20 -0
  229. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/bry_time/.zattrs +8 -0
  230. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/bry_time/0 +0 -0
  231. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_east/.zarray +24 -0
  232. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_east/.zattrs +10 -0
  233. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_east/0.0.0 +0 -0
  234. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_north/.zarray +24 -0
  235. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_north/.zattrs +10 -0
  236. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_north/0.0.0 +0 -0
  237. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_south/.zarray +24 -0
  238. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_south/.zattrs +10 -0
  239. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_south/0.0.0 +0 -0
  240. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_west/.zarray +24 -0
  241. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_west/.zattrs +10 -0
  242. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_west/0.0.0 +0 -0
  243. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_east/.zarray +24 -0
  244. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_east/.zattrs +10 -0
  245. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_east/0.0.0 +0 -0
  246. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_north/.zarray +24 -0
  247. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_north/.zattrs +10 -0
  248. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_north/0.0.0 +0 -0
  249. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_south/.zarray +24 -0
  250. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_south/.zattrs +10 -0
  251. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_south/0.0.0 +0 -0
  252. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_west/.zarray +24 -0
  253. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_west/.zattrs +10 -0
  254. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_west/0.0.0 +0 -0
  255. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_east/.zarray +24 -0
  256. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_east/.zattrs +10 -0
  257. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_east/0.0.0 +0 -0
  258. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_north/.zarray +24 -0
  259. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_north/.zattrs +10 -0
  260. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_north/0.0.0 +0 -0
  261. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_south/.zarray +24 -0
  262. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_south/.zattrs +10 -0
  263. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_south/0.0.0 +0 -0
  264. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_west/.zarray +24 -0
  265. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_west/.zattrs +10 -0
  266. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_west/0.0.0 +0 -0
  267. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_east/.zarray +24 -0
  268. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_east/.zattrs +10 -0
  269. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_east/0.0.0 +0 -0
  270. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_north/.zarray +24 -0
  271. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_north/.zattrs +10 -0
  272. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_north/0.0.0 +0 -0
  273. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_south/.zarray +24 -0
  274. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_south/.zattrs +10 -0
  275. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_south/0.0.0 +0 -0
  276. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_west/.zarray +24 -0
  277. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_west/.zattrs +10 -0
  278. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_west/0.0.0 +0 -0
  279. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_east/.zarray +24 -0
  280. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_east/.zattrs +10 -0
  281. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_east/0.0.0 +0 -0
  282. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_north/.zarray +24 -0
  283. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_north/.zattrs +10 -0
  284. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_north/0.0.0 +0 -0
  285. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_south/.zarray +24 -0
  286. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_south/.zattrs +10 -0
  287. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_south/0.0.0 +0 -0
  288. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_west/.zarray +24 -0
  289. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_west/.zattrs +10 -0
  290. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_west/0.0.0 +0 -0
  291. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_east/.zarray +24 -0
  292. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_east/.zattrs +10 -0
  293. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_east/0.0.0 +0 -0
  294. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_north/.zarray +24 -0
  295. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_north/.zattrs +10 -0
  296. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_north/0.0.0 +0 -0
  297. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_south/.zarray +24 -0
  298. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_south/.zattrs +10 -0
  299. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_south/0.0.0 +0 -0
  300. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_west/.zarray +24 -0
  301. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_west/.zattrs +10 -0
  302. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_west/0.0.0 +0 -0
  303. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_east/.zarray +24 -0
  304. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_east/.zattrs +10 -0
  305. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_east/0.0.0 +0 -0
  306. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_north/.zarray +24 -0
  307. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_north/.zattrs +10 -0
  308. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_north/0.0.0 +0 -0
  309. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_south/.zarray +24 -0
  310. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_south/.zattrs +10 -0
  311. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_south/0.0.0 +0 -0
  312. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_west/.zarray +24 -0
  313. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_west/.zattrs +10 -0
  314. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_west/0.0.0 +0 -0
  315. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_east/.zarray +24 -0
  316. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_east/.zattrs +10 -0
  317. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_east/0.0.0 +0 -0
  318. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_north/.zarray +24 -0
  319. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_north/.zattrs +10 -0
  320. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_north/0.0.0 +0 -0
  321. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_south/.zarray +24 -0
  322. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_south/.zattrs +10 -0
  323. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_south/0.0.0 +0 -0
  324. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_west/.zarray +24 -0
  325. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_west/.zattrs +10 -0
  326. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_west/0.0.0 +0 -0
  327. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_east/.zarray +24 -0
  328. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_east/.zattrs +10 -0
  329. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_east/0.0.0 +0 -0
  330. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_north/.zarray +24 -0
  331. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_north/.zattrs +10 -0
  332. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_north/0.0.0 +0 -0
  333. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_south/.zarray +24 -0
  334. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_south/.zattrs +10 -0
  335. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_south/0.0.0 +0 -0
  336. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_west/.zarray +24 -0
  337. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_west/.zattrs +10 -0
  338. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_west/0.0.0 +0 -0
  339. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/month/.zarray +20 -0
  340. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/month/.zattrs +6 -0
  341. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/month/0 +0 -0
  342. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_east/.zarray +24 -0
  343. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_east/.zattrs +10 -0
  344. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_east/0.0.0 +0 -0
  345. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_north/.zarray +24 -0
  346. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_north/.zattrs +10 -0
  347. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_north/0.0.0 +0 -0
  348. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_south/.zarray +24 -0
  349. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_south/.zattrs +10 -0
  350. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_south/0.0.0 +0 -0
  351. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_west/.zarray +24 -0
  352. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_west/.zattrs +10 -0
  353. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_west/0.0.0 +0 -0
  354. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_east/.zarray +24 -0
  355. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_east/.zattrs +10 -0
  356. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_east/0.0.0 +0 -0
  357. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_north/.zarray +24 -0
  358. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_north/.zattrs +10 -0
  359. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_north/0.0.0 +0 -0
  360. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_south/.zarray +24 -0
  361. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_south/.zattrs +10 -0
  362. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_south/0.0.0 +0 -0
  363. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_west/.zarray +24 -0
  364. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_west/.zattrs +10 -0
  365. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_west/0.0.0 +0 -0
  366. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_east/.zarray +24 -0
  367. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_east/.zattrs +10 -0
  368. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_east/0.0.0 +0 -0
  369. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_north/.zarray +24 -0
  370. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_north/.zattrs +10 -0
  371. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_north/0.0.0 +0 -0
  372. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_south/.zarray +24 -0
  373. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_south/.zattrs +10 -0
  374. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_south/0.0.0 +0 -0
  375. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_west/.zarray +24 -0
  376. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_west/.zattrs +10 -0
  377. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_west/0.0.0 +0 -0
  378. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_east/.zarray +24 -0
  379. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_east/.zattrs +10 -0
  380. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_east/0.0.0 +0 -0
  381. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_north/.zarray +24 -0
  382. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_north/.zattrs +10 -0
  383. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_north/0.0.0 +0 -0
  384. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_south/.zarray +24 -0
  385. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_south/.zattrs +10 -0
  386. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_south/0.0.0 +0 -0
  387. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_west/.zarray +24 -0
  388. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_west/.zattrs +10 -0
  389. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_west/0.0.0 +0 -0
  390. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_east/.zarray +24 -0
  391. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_east/.zattrs +10 -0
  392. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_east/0.0.0 +0 -0
  393. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_north/.zarray +24 -0
  394. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_north/.zattrs +10 -0
  395. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_north/0.0.0 +0 -0
  396. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_south/.zarray +24 -0
  397. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_south/.zattrs +10 -0
  398. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_south/0.0.0 +0 -0
  399. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_west/.zarray +24 -0
  400. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_west/.zattrs +10 -0
  401. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_west/0.0.0 +0 -0
  402. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_east/.zarray +24 -0
  403. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_east/.zattrs +10 -0
  404. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_east/0.0.0 +0 -0
  405. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_north/.zarray +24 -0
  406. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_north/.zattrs +10 -0
  407. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_north/0.0.0 +0 -0
  408. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_south/.zarray +24 -0
  409. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_south/.zattrs +10 -0
  410. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_south/0.0.0 +0 -0
  411. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_west/.zarray +24 -0
  412. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_west/.zattrs +10 -0
  413. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_west/0.0.0 +0 -0
  414. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/.zattrs +12 -0
  415. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/.zgroup +3 -0
  416. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/.zmetadata +424 -0
  417. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/abs_time/.zarray +20 -0
  418. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/abs_time/.zattrs +8 -0
  419. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/abs_time/0 +0 -0
  420. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/dust/.zarray +24 -0
  421. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/dust/.zattrs +12 -0
  422. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/dust/0.0.0 +0 -0
  423. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/dust_time/.zarray +20 -0
  424. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/dust_time/.zattrs +8 -0
  425. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/dust_time/0 +0 -0
  426. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/iron/.zarray +24 -0
  427. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/iron/.zattrs +12 -0
  428. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/iron/0.0.0 +0 -0
  429. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/iron_time/.zarray +20 -0
  430. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/iron_time/.zattrs +8 -0
  431. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/iron_time/0 +0 -0
  432. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/month/.zarray +20 -0
  433. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/month/.zattrs +6 -0
  434. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/month/0 +0 -0
  435. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/nhy/.zarray +24 -0
  436. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/nhy/.zattrs +10 -0
  437. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/nhy/0.0.0 +0 -0
  438. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/nhy_time/.zarray +20 -0
  439. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/nhy_time/.zattrs +8 -0
  440. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/nhy_time/0 +0 -0
  441. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/nox/.zarray +24 -0
  442. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/nox/.zattrs +10 -0
  443. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/nox/0.0.0 +0 -0
  444. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/nox_time/.zarray +20 -0
  445. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/nox_time/.zattrs +8 -0
  446. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/nox_time/0 +0 -0
  447. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/pco2_air/.zarray +24 -0
  448. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/pco2_air/.zattrs +12 -0
  449. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/pco2_air/0.0.0 +0 -0
  450. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/pco2_air_alt/.zarray +24 -0
  451. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/pco2_air_alt/.zattrs +10 -0
  452. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/pco2_air_alt/0.0.0 +0 -0
  453. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/pco2_time/.zarray +20 -0
  454. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/pco2_time/.zattrs +8 -0
  455. roms_tools/tests/test_setup/test_data/bgc_surface_forcing_from_unified_climatology.zarr/pco2_time/0 +0 -0
  456. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/.zattrs +12 -0
  457. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/.zgroup +3 -0
  458. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/.zmetadata +1600 -0
  459. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ALK/.zarray +26 -0
  460. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ALK/.zattrs +11 -0
  461. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ALK/0.0.0.0 +0 -0
  462. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ALK_ALT_CO2/.zarray +26 -0
  463. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ALK_ALT_CO2/.zattrs +11 -0
  464. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ALK_ALT_CO2/0.0.0.0 +0 -0
  465. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/Cs_r/.zarray +20 -0
  466. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/Cs_r/.zattrs +7 -0
  467. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/Cs_r/0 +0 -0
  468. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/Cs_w/.zarray +20 -0
  469. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/Cs_w/.zattrs +7 -0
  470. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/Cs_w/0 +0 -0
  471. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DIC/.zarray +26 -0
  472. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DIC/.zattrs +11 -0
  473. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DIC/0.0.0.0 +0 -0
  474. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DIC_ALT_CO2/.zarray +26 -0
  475. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DIC_ALT_CO2/.zattrs +11 -0
  476. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DIC_ALT_CO2/0.0.0.0 +0 -0
  477. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DOC/.zarray +26 -0
  478. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DOC/.zattrs +11 -0
  479. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DOC/0.0.0.0 +0 -0
  480. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DOCr/.zarray +26 -0
  481. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DOCr/.zattrs +11 -0
  482. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DOCr/0.0.0.0 +0 -0
  483. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DON/.zarray +26 -0
  484. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DON/.zattrs +11 -0
  485. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DON/0.0.0.0 +0 -0
  486. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DONr/.zarray +26 -0
  487. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DONr/.zattrs +11 -0
  488. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DONr/0.0.0.0 +0 -0
  489. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DOP/.zarray +26 -0
  490. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DOP/.zattrs +11 -0
  491. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DOP/0.0.0.0 +0 -0
  492. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DOPr/.zarray +26 -0
  493. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DOPr/.zattrs +11 -0
  494. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/DOPr/0.0.0.0 +0 -0
  495. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/Fe/.zarray +26 -0
  496. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/Fe/.zattrs +11 -0
  497. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/Fe/0.0.0.0 +0 -0
  498. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/Lig/.zarray +26 -0
  499. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/Lig/.zattrs +11 -0
  500. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/Lig/0.0.0.0 +0 -0
  501. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/NH4/.zarray +26 -0
  502. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/NH4/.zattrs +11 -0
  503. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/NH4/0.0.0.0 +0 -0
  504. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/NO3/.zarray +26 -0
  505. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/NO3/.zattrs +11 -0
  506. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/NO3/0.0.0.0 +0 -0
  507. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/O2/.zarray +26 -0
  508. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/O2/.zattrs +11 -0
  509. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/O2/0.0.0.0 +0 -0
  510. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/PO4/.zarray +26 -0
  511. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/PO4/.zattrs +11 -0
  512. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/PO4/0.0.0.0 +0 -0
  513. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/SiO3/.zarray +26 -0
  514. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/SiO3/.zattrs +11 -0
  515. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/SiO3/0.0.0.0 +0 -0
  516. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/abs_time/.zarray +20 -0
  517. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/abs_time/.zattrs +8 -0
  518. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/abs_time/0 +0 -0
  519. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatC/.zarray +26 -0
  520. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatC/.zattrs +11 -0
  521. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatC/0.0.0.0 +0 -0
  522. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatChl/.zarray +26 -0
  523. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatChl/.zattrs +11 -0
  524. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatChl/0.0.0.0 +0 -0
  525. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatFe/.zarray +26 -0
  526. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatFe/.zattrs +11 -0
  527. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatFe/0.0.0.0 +0 -0
  528. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatP/.zarray +26 -0
  529. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatP/.zattrs +11 -0
  530. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatP/0.0.0.0 +0 -0
  531. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatSi/.zarray +26 -0
  532. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatSi/.zattrs +11 -0
  533. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diatSi/0.0.0.0 +0 -0
  534. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diazC/.zarray +26 -0
  535. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diazC/.zattrs +11 -0
  536. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diazC/0.0.0.0 +0 -0
  537. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diazChl/.zarray +26 -0
  538. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diazChl/.zattrs +11 -0
  539. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diazChl/0.0.0.0 +0 -0
  540. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diazFe/.zarray +26 -0
  541. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diazFe/.zattrs +11 -0
  542. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diazFe/0.0.0.0 +0 -0
  543. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diazP/.zarray +26 -0
  544. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diazP/.zattrs +11 -0
  545. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/diazP/0.0.0.0 +0 -0
  546. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ocean_time/.zarray +20 -0
  547. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ocean_time/.zattrs +7 -0
  548. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ocean_time/0 +0 -0
  549. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/salt/.zarray +26 -0
  550. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/salt/.zattrs +11 -0
  551. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/salt/0.0.0.0 +0 -0
  552. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spC/.zarray +26 -0
  553. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spC/.zattrs +11 -0
  554. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spC/0.0.0.0 +0 -0
  555. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spCaCO3/.zarray +26 -0
  556. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spCaCO3/.zattrs +11 -0
  557. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spCaCO3/0.0.0.0 +0 -0
  558. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spChl/.zarray +26 -0
  559. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spChl/.zattrs +11 -0
  560. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spChl/0.0.0.0 +0 -0
  561. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spFe/.zarray +26 -0
  562. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spFe/.zattrs +11 -0
  563. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spFe/0.0.0.0 +0 -0
  564. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spP/.zarray +26 -0
  565. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spP/.zattrs +11 -0
  566. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/spP/0.0.0.0 +0 -0
  567. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/temp/.zarray +26 -0
  568. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/temp/.zattrs +11 -0
  569. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/temp/0.0.0.0 +0 -0
  570. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/u/.zarray +26 -0
  571. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/u/.zattrs +11 -0
  572. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/u/0.0.0.0 +0 -0
  573. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ubar/.zarray +24 -0
  574. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ubar/.zattrs +10 -0
  575. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ubar/0.0.0 +0 -0
  576. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/v/.zarray +26 -0
  577. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/v/.zattrs +11 -0
  578. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/v/0.0.0.0 +0 -0
  579. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/vbar/.zarray +24 -0
  580. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/vbar/.zattrs +10 -0
  581. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/vbar/0.0.0 +0 -0
  582. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/w/.zarray +26 -0
  583. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/w/.zattrs +11 -0
  584. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/w/0.0.0.0 +0 -0
  585. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/zeta/.zarray +24 -0
  586. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/zeta/.zattrs +10 -0
  587. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/zeta/0.0.0 +0 -0
  588. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/zooC/.zarray +26 -0
  589. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/zooC/.zattrs +11 -0
  590. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/zooC/0.0.0.0 +0 -0
  591. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/.zmetadata +86 -4
  592. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/{river_flux → river_fraction}/.zattrs +1 -1
  593. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_fraction/0.0 +0 -0
  594. roms_tools/tests/test_setup/test_data/{river_forcing_with_bgc.zarr/river_flux → river_forcing_no_climatology.zarr/river_index}/.zattrs +1 -1
  595. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_index/0.0 +0 -0
  596. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_tracer/.zattrs +1 -1
  597. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_long_name/.zarray +20 -0
  598. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_long_name/.zattrs +6 -0
  599. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_long_name/0 +0 -0
  600. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_unit/.zarray +20 -0
  601. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_unit/.zattrs +6 -0
  602. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/tracer_unit/0 +0 -0
  603. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/.zmetadata +86 -4
  604. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_fraction/.zarray +22 -0
  605. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_fraction/.zattrs +8 -0
  606. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_fraction/0.0 +0 -0
  607. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_index/.zarray +22 -0
  608. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_index/.zattrs +8 -0
  609. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_index/0.0 +0 -0
  610. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_tracer/.zattrs +1 -1
  611. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/tracer_long_name/.zarray +20 -0
  612. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/tracer_long_name/.zattrs +6 -0
  613. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/tracer_long_name/0 +0 -0
  614. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/tracer_unit/.zarray +20 -0
  615. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/tracer_unit/.zattrs +6 -0
  616. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/tracer_unit/0 +0 -0
  617. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/.zattrs +1 -2
  618. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/.zmetadata +27 -5
  619. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ntides/.zarray +20 -0
  620. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ntides/.zattrs +5 -0
  621. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ntides/0 +0 -0
  622. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/omega/.zattrs +1 -3
  623. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/pot_Im/0.0.0 +0 -0
  624. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/pot_Re/0.0.0 +0 -0
  625. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ssh_Im/0.0.0 +0 -0
  626. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/ssh_Re/0.0.0 +0 -0
  627. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Im/0.0.0 +0 -0
  628. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Re/0.0.0 +0 -0
  629. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Im/0.0.0 +0 -0
  630. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Re/0.0.0 +0 -0
  631. roms_tools/tests/test_setup/test_datasets.py +105 -1
  632. roms_tools/tests/test_setup/test_initial_conditions.py +112 -25
  633. roms_tools/tests/test_setup/test_river_forcing.py +4 -3
  634. roms_tools/tests/test_setup/test_surface_forcing.py +67 -41
  635. roms_tools/tests/test_setup/test_tides.py +112 -47
  636. roms_tools/tests/test_setup/test_validation.py +6 -0
  637. roms_tools/utils.py +115 -1
  638. {roms_tools-2.6.1.dist-info → roms_tools-2.7.0.dist-info}/METADATA +1 -3
  639. {roms_tools-2.6.1.dist-info → roms_tools-2.7.0.dist-info}/RECORD +644 -47
  640. {roms_tools-2.6.1.dist-info → roms_tools-2.7.0.dist-info}/WHEEL +1 -1
  641. roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/river_flux/0.0 +0 -0
  642. roms_tools/tests/test_setup/test_data/river_forcing_with_bgc.zarr/river_flux/0.0 +0 -0
  643. /roms_tools/tests/test_setup/test_data/river_forcing_no_climatology.zarr/{river_flux → river_fraction}/.zarray +0 -0
  644. /roms_tools/tests/test_setup/test_data/{river_forcing_with_bgc.zarr/river_flux → river_forcing_no_climatology.zarr/river_index}/.zarray +0 -0
  645. {roms_tools-2.6.1.dist-info → roms_tools-2.7.0.dist-info}/licenses/LICENSE +0 -0
  646. {roms_tools-2.6.1.dist-info → roms_tools-2.7.0.dist-info}/top_level.txt +0 -0
@@ -6,10 +6,12 @@ import numpy as np
6
6
  from typing import Dict, Optional, Union, List
7
7
  from pathlib import Path
8
8
  import logging
9
+ from roms_tools.constants import R_EARTH
9
10
  from roms_tools.utils import _load_data
10
11
  from roms_tools.setup.utils import (
11
12
  assign_dates_to_climatology,
12
13
  interpolate_from_climatology,
14
+ interpolate_cyclic_time,
13
15
  get_time_type,
14
16
  convert_cftime_to_datetime,
15
17
  one_dim_fill,
@@ -19,6 +21,7 @@ from roms_tools.download import (
19
21
  download_correction_data,
20
22
  download_topo,
21
23
  download_river_data,
24
+ download_sal_data,
22
25
  )
23
26
  from roms_tools.setup.fill import LateralFill
24
27
 
@@ -44,8 +47,15 @@ class Dataset:
44
47
  Dictionary specifying the names of dimensions in the dataset.
45
48
  var_names: Dict[str, str]
46
49
  Dictionary of variable names that are required in the dataset.
50
+ opt_var_names: Dict[str, str], optional
51
+ Dictionary of variable names that are optional in the dataset.
52
+ Defaults to an empty dictionary.
47
53
  climatology : bool
48
54
  Indicates whether the dataset is climatological. Defaults to False.
55
+ needs_lateral_fill: bool, optional
56
+ Indicates whether land values require lateral filling. If `True`, ocean values will be extended into land areas
57
+ to replace NaNs or non-ocean values (such as atmospheric values in ERA5 data). If `False`, it is assumed that
58
+ land values are already correctly assigned, and lateral filling will be skipped. Defaults to `True`.
49
59
  use_dask: bool
50
60
  Indicates whether to use dask for chunking. If True, data is loaded with dask; if False, data is loaded eagerly. Defaults to False.
51
61
  apply_post_processing: bool
@@ -78,7 +88,9 @@ class Dataset:
78
88
  }
79
89
  )
80
90
  var_names: Dict[str, str]
91
+ opt_var_names: Optional[Dict[str, str]] = field(default_factory=dict)
81
92
  climatology: Optional[bool] = False
93
+ needs_lateral_fill: Optional[bool] = True
82
94
  use_dask: Optional[bool] = False
83
95
  apply_post_processing: Optional[bool] = True
84
96
 
@@ -109,6 +121,9 @@ class Dataset:
109
121
  ds = self.clean_up(ds)
110
122
  self.check_dataset(ds)
111
123
 
124
+ # Select relevant fields
125
+ ds = self.select_relevant_fields(ds)
126
+
112
127
  # Select relevant times
113
128
  if "time" in self.dim_names and self.start_time is not None:
114
129
  ds = self.add_time_info(ds)
@@ -117,9 +132,6 @@ class Dataset:
117
132
  if self.dim_names["time"] != "time":
118
133
  ds = ds.rename({self.dim_names["time"]: "time"})
119
134
 
120
- # Select relevant fields
121
- ds = self.select_relevant_fields(ds)
122
-
123
135
  # Make sure that latitude is ascending
124
136
  ds = self.ensure_dimension_is_ascending(ds, dim="latitude")
125
137
  # Make sure there are no 360 degree jumps in longitude
@@ -158,7 +170,7 @@ class Dataset:
158
170
 
159
171
  return ds
160
172
 
161
- def clean_up(self, ds: xr.Dataset) -> xr.Dataset:
173
+ def clean_up(self, ds: xr.Dataset, **kwargs) -> xr.Dataset:
162
174
  """Dummy method to be overridden by child classes to clean up the dataset.
163
175
 
164
176
  This method is intended as a placeholder and should be implemented in subclasses
@@ -172,9 +184,9 @@ class Dataset:
172
184
  Returns
173
185
  -------
174
186
  xr.Dataset
175
- The xarray Dataset cleaned up (as implemented by child classes).
187
+ The cleaned-up xarray Dataset (as implemented by child classes).
176
188
  """
177
- return ds
189
+ return ds # Default behavior (no-op, subclasses should override)
178
190
 
179
191
  def check_dataset(self, ds: xr.Dataset) -> None:
180
192
  """Check if the dataset contains the specified variables and dimensions.
@@ -208,7 +220,11 @@ class Dataset:
208
220
  """
209
221
 
210
222
  for var in ds.data_vars:
211
- if var not in self.var_names.values():
223
+ if (
224
+ var not in self.var_names.values()
225
+ and var not in self.opt_var_names.values()
226
+ and var != "mask"
227
+ ):
212
228
  ds = ds.drop_vars(var)
213
229
 
214
230
  return ds
@@ -372,7 +388,6 @@ class Dataset:
372
388
  and longitude differences, in meters.
373
389
  """
374
390
 
375
- r_earth = 6371315.0
376
391
  lat_dim = self.dim_names["latitude"]
377
392
  lon_dim = self.dim_names["longitude"]
378
393
 
@@ -385,11 +400,11 @@ class Dataset:
385
400
  lon_diff = np.abs(np.diff(longitudes)).min() # Minimal longitude spacing
386
401
 
387
402
  # Latitude spacing is constant at all longitudes
388
- min_lat_spacing = (2 * np.pi * r_earth * lat_diff) / 360
403
+ min_lat_spacing = (2 * np.pi * R_EARTH * lat_diff) / 360
389
404
 
390
405
  # Longitude spacing varies with latitude
391
406
  min_lon_spacing = (
392
- 2 * np.pi * r_earth * lon_diff * np.cos(np.radians(latitudes.min()))
407
+ 2 * np.pi * R_EARTH * lon_diff * np.cos(np.radians(latitudes.min()))
393
408
  ) / 360
394
409
 
395
410
  # The minimal spacing is the smaller of the two
@@ -591,6 +606,7 @@ class Dataset:
591
606
  lon = subdomain[self.dim_names["longitude"]]
592
607
 
593
608
  if self.is_global:
609
+ concats = []
594
610
  # Concatenate only if necessary
595
611
  if lon_max + margin > lon.max():
596
612
  # See if shifting by +360 degrees helps
@@ -600,10 +616,7 @@ class Dataset:
600
616
  subdomain[self.dim_names["longitude"]] = lon + 360
601
617
  lon = subdomain[self.dim_names["longitude"]]
602
618
  else:
603
- subdomain = self.concatenate_longitudes(
604
- subdomain, end="upper", verbose=verbose
605
- )
606
- lon = subdomain[self.dim_names["longitude"]]
619
+ concats.append("upper")
607
620
  if lon_min - margin < lon.min():
608
621
  # See if shifting by -360 degrees helps
609
622
  if (lon_min - margin > (lon - 360).min()) and (
@@ -612,10 +625,14 @@ class Dataset:
612
625
  subdomain[self.dim_names["longitude"]] = lon - 360
613
626
  lon = subdomain[self.dim_names["longitude"]]
614
627
  else:
615
- subdomain = self.concatenate_longitudes(
616
- subdomain, end="lower", verbose=verbose
617
- )
618
- lon = subdomain[self.dim_names["longitude"]]
628
+ concats.append("lower")
629
+
630
+ if concats:
631
+ end = "both" if len(concats) == 2 else concats[0]
632
+ subdomain = self.concatenate_longitudes(
633
+ subdomain, end=end, verbose=False
634
+ )
635
+ lon = subdomain[self.dim_names["longitude"]]
619
636
 
620
637
  else:
621
638
  # Adjust longitude range if needed to match the expected range
@@ -639,6 +656,7 @@ class Dataset:
639
656
  lon_min += 360
640
657
  lon_max += 360
641
658
  # Select the subdomain in longitude direction
659
+
642
660
  subdomain = subdomain.sel(
643
661
  **{
644
662
  self.dim_names["longitude"]: slice(lon_min - margin, lon_max + margin),
@@ -682,38 +700,54 @@ class Dataset:
682
700
 
683
701
  Notes
684
702
  -----
703
+ This method assumes that the variables in the dataset use a dimension
704
+ ordering where latitude comes before longitude, i.e., ('latitude', 'longitude').
705
+ Ensure that this convention is followed to avoid unexpected behavior.
706
+
685
707
  Looping over `self.ds.data_vars` instead of `self.var_names` ensures that each
686
708
  dataset variable is filled only once, even if multiple entries in `self.var_names`
687
709
  point to the same variable in the dataset.
688
710
  """
689
- lateral_fill = LateralFill(
690
- self.ds["mask"],
691
- [self.dim_names["latitude"], self.dim_names["longitude"]],
692
- )
693
711
 
694
- separate_fill_for_velocities = False
695
- if "mask_vel" in self.ds.data_vars:
696
- lateral_fill_vel = LateralFill(
697
- self.ds["mask_vel"],
712
+ if self.needs_lateral_fill:
713
+ logging.info(
714
+ "Applying 2D horizontal fill to the source data before regridding."
715
+ )
716
+
717
+ lateral_fill = LateralFill(
718
+ self.ds["mask"],
698
719
  [self.dim_names["latitude"], self.dim_names["longitude"]],
699
720
  )
700
- separate_fill_for_velocities = True
701
-
702
- for var_name in self.ds.data_vars:
703
- if var_name.startswith("mask"):
704
- # Skip variables that are mask types
705
- continue
706
- elif (
707
- separate_fill_for_velocities
708
- and "u" in self.var_names
709
- and "v" in self.var_names
710
- and var_name in [self.var_names["u"], self.var_names["v"]]
711
- ):
712
- # Apply lateral fill with velocity mask for velocity variables if present
713
- self.ds[var_name] = lateral_fill_vel.apply(self.ds[var_name])
714
- else:
715
- # Apply standard lateral fill for other variables
716
- self.ds[var_name] = lateral_fill.apply(self.ds[var_name])
721
+
722
+ separate_fill_for_velocities = False
723
+ # TODO: Replace hardcoded mask detection with a dictionary-based mask selection.
724
+ # This dictionary could assign which mask to use for what fields.
725
+ if "mask_vel" in self.ds.data_vars:
726
+ lateral_fill_vel = LateralFill(
727
+ self.ds["mask_vel"],
728
+ [self.dim_names["latitude"], self.dim_names["longitude"]],
729
+ )
730
+ separate_fill_for_velocities = True
731
+
732
+ for var_name in self.ds.data_vars:
733
+ if var_name.startswith("mask"):
734
+ # Skip variables that are mask types
735
+ continue
736
+ elif (
737
+ separate_fill_for_velocities
738
+ and "u" in self.var_names
739
+ and "v" in self.var_names
740
+ and var_name in [self.var_names["u"], self.var_names["v"]]
741
+ ):
742
+ # Apply lateral fill with velocity mask for velocity variables if present
743
+ self.ds[var_name] = lateral_fill_vel.apply(self.ds[var_name])
744
+ else:
745
+ # Apply standard lateral fill for other variables
746
+ self.ds[var_name] = lateral_fill.apply(self.ds[var_name])
747
+ else:
748
+ logging.info(
749
+ "2D horizontal fill is skipped because source data already contains filled values."
750
+ )
717
751
 
718
752
  def extrapolate_deepest_to_bottom(self):
719
753
  """Extrapolate deepest non-NaN values to fill bottom NaNs along the depth
@@ -775,169 +809,226 @@ class TPXODataset(Dataset):
775
809
  ----------
776
810
  filename : str
777
811
  The path to the TPXO dataset file.
778
- var_names : Dict[str, str], optional
779
- Dictionary of variable names required in the dataset. Defaults to:
780
- {
781
- "h_Re": "h_Re",
782
- "h_Im": "h_Im",
783
- "sal_Re": "sal_Re",
784
- "sal_Im": "sal_Im",
785
- "u_Re": "u_Re",
786
- "u_Im": "u_Im",
787
- "v_Re": "v_Re",
788
- "v_Im": "v_Im",
789
- "depth": "depth"
790
- }
812
+ grid_filename : str
813
+ The path to the TPXO grid file.
814
+ location : str
815
+ "h", "u", "v"
816
+ var_names : Dict[str, str]
817
+ Dictionary of variable names required in the dataset.
791
818
  dim_names : Dict[str, str], optional
792
819
  Dictionary specifying the names of dimensions in the dataset. Defaults to:
793
820
  {"longitude": "ny", "latitude": "nx", "ntides": "nc"}.
821
+ tolerate_coord_mismatch : bool, optional
822
+ If True, allows mismatched latitude/longitude coordinates between the TPXO dataset and the TPXO grid
823
+ by selecting the nearest grid-aligned coordinates. Default is False.
794
824
 
795
825
  Attributes
796
826
  ----------
797
827
  ds : xr.Dataset
798
828
  The xarray Dataset containing the TPXO tidal model data, loaded from the specified file.
799
- reference_date : datetime
800
- The reference date for the TPXO data. Default is datetime(1992, 1, 1).
801
829
  """
802
830
 
803
831
  filename: str
804
- var_names: Dict[str, str] = field(
805
- default_factory=lambda: {
806
- "ssh_Re": "h_Re",
807
- "ssh_Im": "h_Im",
808
- "sal_Re": "sal_Re",
809
- "sal_Im": "sal_Im",
810
- "u_Re": "u_Re",
811
- "u_Im": "u_Im",
812
- "v_Re": "v_Re",
813
- "v_Im": "v_Im",
814
- "depth": "depth",
815
- }
816
- )
832
+ grid_filename: str
833
+ location: str
834
+ var_names: Dict[str, str]
817
835
  dim_names: Dict[str, str] = field(
818
- default_factory=lambda: {"longitude": "ny", "latitude": "nx", "ntides": "nc"}
836
+ default_factory=lambda: {"longitude": "nx", "latitude": "ny", "ntides": "nc"}
819
837
  )
838
+ tolerate_coord_mismatch: bool = False
820
839
  ds: xr.Dataset = field(init=False, repr=False)
821
- reference_date: datetime = datetime(1992, 1, 1)
822
840
 
823
841
  def clean_up(self, ds: xr.Dataset) -> xr.Dataset:
824
- """Clean up and standardize the dimensions and coordinates of the dataset for
825
- further processing.
826
-
827
- This method performs the following operations:
828
- - Assigns new coordinate variables for 'omega', 'longitude', and 'latitude' based on existing dataset variables.
829
- - 'omega' is retained as it is.
830
- - 'longitude' is derived from 'lon_r', assuming it is constant along the 'ny' dimension.
831
- - 'latitude' is derived from 'lat_r', assuming it is constant along the 'nx' dimension.
832
- - Renames the dimensions 'nx' and 'ny' to 'longitude' and 'latitude', respectively, for consistency.
833
- - Renames the tidal dimension to 'ntides' for standardization.
834
- - Updates the `dim_names` attribute of the object to reflect the new dimension names: 'longitude', 'latitude', and 'ntides'.
842
+ """Standardize the dataset's dimensions and coordinates for further processing.
843
+
844
+ This method performs the following operations:
845
+ - Assigns 'longitude' and 'latitude' coordinates from existing dataset variables.
846
+ - Adds a `mask` variable indicating valid data points based on grid conditions.
847
+ - Renames dimensions:
848
+ - 'nx' 'longitude'
849
+ - 'ny' 'latitude'
850
+ - Tidal dimension 'ntides'
851
+ - Updates `dim_names` to reflect the new dimension names.
852
+ - If coordinates do not match and `self.tolerate_coord_mismatch=True`, the dataset is reindexed
853
+ to the grid's coordinates using nearest-neighbor selection. Otherwise, a ValueError is raised.
854
+
855
+ Parameters
856
+ ----------
857
+ ds : xr.Dataset
858
+ The dataset to be standardized.
859
+
860
+ Returns
861
+ -------
862
+ xr.Dataset
863
+ The cleaned dataset with updated coordinates and dimensions.
864
+
865
+ Raises
866
+ ------
867
+ ValueError
868
+ If longitude or latitude values do not match the grid.
869
+ """
835
870
 
836
- Parameters
837
- ----------
838
- ds : xr.Dataset
839
- The input dataset to be cleaned and standardized. It should contain the coordinates 'omega', 'lon_r', 'lat_r', and the tidal dimension.
871
+ ds_grid = _load_data(self.grid_filename, self.dim_names, self.use_dask)
872
+
873
+ # Define mask and coordinate names based on location
874
+ if self.location == "h":
875
+ mask_name = "mz"
876
+ lon_name = "lon_z"
877
+ lat_name = "lat_z"
878
+ elif self.location == "u":
879
+ mask_name = "mu"
880
+ lon_name = "lon_u"
881
+ lat_name = "lat_u"
882
+ elif self.location == "v":
883
+ mask_name = "mv"
884
+ lon_name = "lon_v"
885
+ lat_name = "lat_v"
886
+
887
+ # Assign and rename coordinates
888
+ ds_grid = ds_grid.assign_coords(
889
+ {
890
+ "nx": ds_grid[lon_name].isel(
891
+ ny=0
892
+ ), # lon is constant along ny, i.e., is only a function of nx
893
+ "ny": ds_grid[lat_name].isel(
894
+ nx=0
895
+ ), # lat is constant along nx, i.e., is only a function of ny
896
+ }
897
+ )
898
+ ds_grid = ds_grid.rename({"nx": "longitude", "ny": "latitude"})
840
899
 
841
- Returns
842
- -------
843
- ds : xr.Dataset
844
- A cleaned and standardized `xarray.Dataset` with updated coordinates and dimensions.
845
- """
900
+ # Drop all dimensions except 'longitude' and 'latitude'
901
+ dims_to_keep = {"longitude", "latitude"}
902
+ dims_to_drop = [dim for dim in ds_grid.dims if dim not in dims_to_keep]
903
+ if dims_to_drop:
904
+ ds_grid = ds_grid.isel({dim: 0 for dim in dims_to_drop})
905
+
906
+ # Ensure correct dimension order
907
+ ds_grid = ds_grid.transpose("latitude", "longitude")
908
+
909
+ dims_to_keep = {"longitude", "latitude"}
910
+ dims_to_drop = set(ds_grid.dims) - dims_to_keep
911
+ ds_grid = (
912
+ ds_grid.isel({dim: 0 for dim in dims_to_drop}) if dims_to_drop else ds_grid
913
+ )
914
+ # Bring dimensions in correct order
915
+ ds_grid = ds_grid.transpose("latitude", "longitude")
916
+
917
+ ds = ds.rename({"con": "nc"})
846
918
  ds = ds.assign_coords(
847
919
  {
848
- "omega": ds["omega"],
849
- "nx": ds["lon_r"].isel(
920
+ "nc": ("nc", [c.strip() for c in ds["nc"].values]), # Strip padding
921
+ "nx": ds[lon_name].isel(
850
922
  ny=0
851
- ), # lon_r is constant along ny, i.e., is only a function of nx
852
- "ny": ds["lat_r"].isel(
923
+ ), # lon is constant along ny, i.e., is only a function of nx
924
+ "ny": ds[lat_name].isel(
853
925
  nx=0
854
- ), # lat_r is constant along nx, i.e., is only a function of ny
926
+ ), # lat is constant along nx, i.e., is only a function of ny
855
927
  }
856
928
  )
857
929
  ds = ds.rename(
858
930
  {"nx": "longitude", "ny": "latitude", self.dim_names["ntides"]: "ntides"}
859
931
  )
860
932
 
933
+ ds = ds.transpose("latitude", "longitude", "ntides")
934
+
861
935
  self.dim_names = {
862
936
  "latitude": "latitude",
863
937
  "longitude": "longitude",
864
938
  "ntides": "ntides",
865
939
  }
866
940
 
941
+ if self.tolerate_coord_mismatch:
942
+ # Reindex dataset to match grid lat/lon using nearest-neighbor method
943
+ ds = ds.sel(
944
+ {
945
+ "latitude": ds_grid["latitude"],
946
+ "longitude": ds_grid["longitude"],
947
+ },
948
+ method="nearest",
949
+ )
950
+
951
+ # Validate matching lat/lon shapes and values
952
+ for coord in [lon_name, lat_name]:
953
+ if ds[coord].shape != ds_grid[coord].shape:
954
+ raise ValueError(
955
+ f"Mismatch in {coord} array sizes. Dataset: {ds[coord].shape}, Grid: {ds_grid[coord].shape}"
956
+ )
957
+ if not np.allclose(ds[coord].values, ds_grid[coord].values):
958
+ raise ValueError(
959
+ f"{coord.capitalize()} values from dataset do not match grid. Dataset: {ds[coord].values}, Grid: {ds_grid[coord].values}"
960
+ )
961
+
962
+ # Add mask
963
+ mask = ds_grid[mask_name].isnull()
964
+ # Create a fresh xarray.DataArray for the mask using only the dimension names.
965
+ # This avoids issues that can arise from small coordinate mismatches when assigning directly.
966
+ ds["mask"] = xr.DataArray(
967
+ ds_grid[mask_name].isnull().values, dims=list(mask.dims)
968
+ )
969
+
867
970
  return ds
868
971
 
869
- def check_number_constituents(self, ntides: int):
870
- """Checks if the number of constituents in the dataset is at least `ntides`.
972
+ def select_constituents(self, ntides: int, omega: Dict[str, float]):
973
+ """Selects the first `ntides` tidal constituents based on the provided omega
974
+ values.
975
+
976
+ This method filters the dataset to retain only the tidal constituents that match
977
+ the first `ntides` from the provided `omega` dictionary. It ensures that the dataset
978
+ contains the expected constituents before proceeding with the selection. If the dataset
979
+ does not contain the required constituents, an error is raised.
871
980
 
872
981
  Parameters
873
982
  ----------
874
983
  ntides : int
875
- The required number of tidal constituents.
984
+ The number of tidal constituents to retain from the omega values. The method selects
985
+ the first `ntides` constituents based on the provided omega dictionary and maps their
986
+ corresponding values to the dataset.
987
+
988
+ omega : dict
989
+ A dictionary where keys are tidal constituent names and values are their associated omega
990
+ values. The first `ntides` keys from this dictionary will be used to filter the tidal
991
+ constituents in the dataset.
876
992
 
877
993
  Raises
878
994
  ------
879
995
  ValueError
880
- If the number of constituents in the dataset is less than `ntides`.
996
+ If the dataset does not contain all required tidal constituents from the first `ntides`
997
+ selected from the `omega` dictionary, a `ValueError` is raised, indicating the mismatch
998
+ between the expected and present constituents in the dataset.
881
999
  """
882
- if len(self.ds[self.dim_names["ntides"]]) < ntides:
883
- raise ValueError(
884
- f"The dataset contains fewer than {ntides} tidal constituents."
885
- )
886
1000
 
887
- def post_process(self):
888
- """Apply a depth-based mask to the dataset, ensuring only positive depths are
889
- retained.
1001
+ # Expected constituents based on the first 'ntides' from the omega dictionary
1002
+ expected_constituents = list(omega.keys())[:ntides]
890
1003
 
891
- This method checks if the 'depth' variable is present in the dataset. If found, a mask is created where
892
- depths greater than 0 are considered valid (mask value of 1). This mask is applied to all data variables
893
- in the dataset, replacing values at invalid depths (depth ≤ 0) with NaN. The mask itself is also stored
894
- in the dataset under the variable 'mask'.
1004
+ # Extract the current tidal constituents from the dataset
1005
+ dataset_constituents = [
1006
+ c.decode("utf-8").strip() for c in self.ds["ntides"].values
1007
+ ]
895
1008
 
896
- Returns
897
- -------
898
- None
899
- The dataset is modified in-place by applying the mask to each variable.
900
- """
1009
+ # Check if the dataset contains the expected constituents
1010
+ if not all(c in dataset_constituents for c in expected_constituents):
1011
+ raise ValueError(
1012
+ f"The dataset contains tidal constituents {dataset_constituents} that do not match the first {ntides} required constituents "
1013
+ f"from the TPXO dataset: {expected_constituents}. "
1014
+ "Ensure the dataset includes the required constituents or reduce the 'ntides' parameter."
1015
+ )
901
1016
 
902
- if "depth" in self.var_names.keys():
903
- ds = self.ds
904
- mask = xr.where(self.ds["depth"] > 0, 1, 0)
905
- ds["mask"] = mask
906
- ds = ds.drop_vars(["depth"])
1017
+ # Select only the expected constituents from the dataset
1018
+ filtered_constituents = [
1019
+ c for c in dataset_constituents if c in expected_constituents
1020
+ ]
907
1021
 
908
- self.ds = ds
1022
+ # Encode the filtered constituents back to byte strings before selecting in xarray
1023
+ filtered_constituents_bytes = [c.encode("utf-8") for c in filtered_constituents]
909
1024
 
910
- # Remove "depth" from var_names
911
- updated_var_names = {**self.var_names} # Create a copy of the dictionary
912
- updated_var_names.pop("depth", None) # Remove "depth" if it exists
913
- self.var_names = updated_var_names
1025
+ # Update the dataset with the filtered constituents
1026
+ self.ds = self.ds.sel(ntides=filtered_constituents_bytes)
914
1027
 
915
1028
 
916
1029
  @dataclass(kw_only=True)
917
1030
  class GLORYSDataset(Dataset):
918
- """Represents GLORYS data on original grid.
919
-
920
- Parameters
921
- ----------
922
- filename : str
923
- The path to the data files. Can contain wildcards.
924
- start_time : Optional[datetime], optional
925
- The start time for selecting relevant data. If not provided, the data is not filtered by start time.
926
- end_time : Optional[datetime], optional
927
- The end time for selecting relevant data. If not provided, only data at the start_time is selected if start_time is provided,
928
- or no filtering is applied if start_time is not provided.
929
- var_names: Dict[str, str], optional
930
- Dictionary of variable names that are required in the dataset.
931
- dim_names: Dict[str, str], optional
932
- Dictionary specifying the names of dimensions in the dataset.
933
- climatology : bool
934
- Indicates whether the dataset is climatological. Defaults to False.
935
-
936
- Attributes
937
- ----------
938
- ds : xr.Dataset
939
- The xarray Dataset containing the GLORYS data on its original grid.
940
- """
1031
+ """Represents GLORYS data on original grid."""
941
1032
 
942
1033
  var_names: Dict[str, str] = field(
943
1034
  default_factory=lambda: {
@@ -993,31 +1084,159 @@ class GLORYSDataset(Dataset):
993
1084
 
994
1085
 
995
1086
  @dataclass(kw_only=True)
996
- class CESMDataset(Dataset):
997
- """Represents CESM data on original grid.
1087
+ class UnifiedDataset(Dataset):
1088
+ """Represents unified BGC data on original grid.
998
1089
 
999
- Parameters
1000
- ----------
1001
- filename : str
1002
- The path to the data files. Can contain wildcards.
1003
- start_time : Optional[datetime], optional
1004
- The start time for selecting relevant data. If not provided, the data is not filtered by start time.
1005
- end_time : Optional[datetime], optional
1006
- The end time for selecting relevant data. If not provided, only data at the start_time is selected if start_time is provided,
1007
- or no filtering is applied if start_time is not provided.
1008
- var_names: Dict[str, str], optional
1009
- Dictionary of variable names that are required in the dataset.
1010
- dim_names: Dict[str, str], optional
1011
- Dictionary specifying the names of dimensions in the dataset.
1012
- climatology : bool
1013
- Indicates whether the dataset is climatological. Defaults to False.
1014
-
1015
- Attributes
1016
- ----------
1017
- ds : xr.Dataset
1018
- The xarray Dataset containing the CESM data on its original grid.
1090
+ Notes
1091
+ -----
1092
+ Pierre has already addressed lateral filling during preprocessing,
1093
+ and since the dataset does not contain a mask, the `needs_lateral_fill`
1094
+ attribute is set to `False`.
1019
1095
  """
1020
1096
 
1097
+ needs_lateral_fill: Optional[bool] = False
1098
+
1099
+ # overwrite clean_up method from parent class
1100
+ def clean_up(self, ds: xr.Dataset) -> xr.Dataset:
1101
+ """Ensure the dataset's time dimension is correctly defined and standardized.
1102
+
1103
+ This method verifies that the time dimension exists in the dataset and assigns it appropriately. If the "time" dimension is missing, the method attempts to assign an existing "time" or "month" dimension. If neither exists, it expands the dataset to include a "time" dimension with a size of one.
1104
+
1105
+ Returns
1106
+ -------
1107
+ ds : xr.Dataset
1108
+ The xarray Dataset with the correct time dimension assigned or added.
1109
+ """
1110
+
1111
+ ds = ds.rename({"lon": "longitude", "lat": "latitude", "dep": "depth"})
1112
+ ds = ds.assign_coords(
1113
+ {
1114
+ "latitude": ds["latitude"],
1115
+ "longitude": ds["longitude"],
1116
+ "depth": ds["depth"],
1117
+ }
1118
+ )
1119
+
1120
+ self.dim_names = {
1121
+ "latitude": "latitude",
1122
+ "longitude": "longitude",
1123
+ "depth": "depth",
1124
+ }
1125
+
1126
+ # Handle time dimension
1127
+ if "time" not in self.dim_names:
1128
+ if "month" in ds.dims or "season" in ds.dims:
1129
+ time_dim = "month" if "month" in ds.dims else "season"
1130
+
1131
+ if time_dim == "month":
1132
+ # Interpolate season to month so all variables have the same time dimension
1133
+ for var_name in list(self.var_names.values()) + list(
1134
+ self.opt_var_names.values()
1135
+ ):
1136
+ if var_name in ds.data_vars and "season" in ds[var_name].dims:
1137
+ ds[var_name] = interpolate_cyclic_time(
1138
+ ds[var_name],
1139
+ time_dim_name="season",
1140
+ day_of_year=ds["month"],
1141
+ )
1142
+
1143
+ # Rename dimension and convert from float64 days to timedelta
1144
+ ds = ds.rename({time_dim: "time"})
1145
+ self.dim_names["time"] = "time"
1146
+
1147
+ ds["time"] = xr.DataArray(
1148
+ (ds["time"].values * 86400 * 1e9).astype("timedelta64[ns]"),
1149
+ dims="time",
1150
+ )
1151
+
1152
+ else:
1153
+ # Handle case where all variables are time-invariant
1154
+ ds = ds.expand_dims(time=1)
1155
+ self.dim_names["time"] = "time"
1156
+
1157
+ return ds
1158
+
1159
+
1160
+ @dataclass(kw_only=True)
1161
+ class UnifiedBGCDataset(UnifiedDataset):
1162
+ dim_names: Dict[str, str] = field(
1163
+ default_factory=lambda: {
1164
+ "longitude": "lon",
1165
+ "latitude": "lat",
1166
+ "depth": "dep",
1167
+ }
1168
+ )
1169
+ var_names: Dict[str, str] = field(
1170
+ default_factory=lambda: {
1171
+ "PO4": "PO4",
1172
+ "NO3": "NO3",
1173
+ "SiO3": "SiO3",
1174
+ "Fe": "Fe",
1175
+ "O2": "O2",
1176
+ "DIC": "DIC",
1177
+ "ALK": "Alk",
1178
+ }
1179
+ )
1180
+ opt_var_names: Dict[str, str] = field(
1181
+ default_factory=lambda: {
1182
+ "NH4": "NH4",
1183
+ "Lig": "Lig",
1184
+ "DIC_ALT_CO2": "DIC_ALT_CO2",
1185
+ "ALK_ALT_CO2": "Alk_ALT_CO2",
1186
+ "DOC": "DOC",
1187
+ "DON": "DON",
1188
+ "DOP": "DOP",
1189
+ "DOPr": "DOPr",
1190
+ "DONr": "DONr",
1191
+ "DOCr": "DOCr",
1192
+ "spChl": "spChl",
1193
+ "spC": "spC",
1194
+ "spP": "spP",
1195
+ "spFe": "spFe",
1196
+ "diatChl": "diatChl",
1197
+ "diatC": "diatC",
1198
+ "diatP": "diatP",
1199
+ "diatFe": "diatFe",
1200
+ "diatSi": "diatSi",
1201
+ "diazChl": "diazChl",
1202
+ "diazC": "diazC",
1203
+ "diazP": "diazP",
1204
+ "diazFe": "diazFe",
1205
+ "spCaCO3": "spCaCO3",
1206
+ "zooC": "zooC",
1207
+ "CHL": "CHL",
1208
+ }
1209
+ )
1210
+
1211
+ climatology: Optional[bool] = True
1212
+
1213
+
1214
+ @dataclass(kw_only=True)
1215
+ class UnifiedBGCSurfaceDataset(UnifiedDataset):
1216
+ dim_names: Dict[str, str] = field(
1217
+ default_factory=lambda: {
1218
+ "longitude": "lon",
1219
+ "latitude": "lat",
1220
+ }
1221
+ )
1222
+ var_names: Dict[str, str] = field(
1223
+ default_factory=lambda: {"pco2_air": "pco2_air", "dust": "dust", "iron": "iron"}
1224
+ )
1225
+ opt_var_names: Dict[str, str] = field(
1226
+ default_factory=lambda: {
1227
+ "pco2_air_alt": "pco2_air_alt",
1228
+ "nox": "nox",
1229
+ "nhy": "nhy",
1230
+ }
1231
+ )
1232
+
1233
+ climatology: Optional[bool] = True
1234
+
1235
+
1236
+ @dataclass(kw_only=True)
1237
+ class CESMDataset(Dataset):
1238
+ """Represents CESM data on original grid."""
1239
+
1021
1240
  # overwrite clean_up method from parent class
1022
1241
  def clean_up(self, ds: xr.Dataset) -> xr.Dataset:
1023
1242
  """Ensure the dataset's time dimension is correctly defined and standardized.
@@ -1080,29 +1299,7 @@ class CESMDataset(Dataset):
1080
1299
 
1081
1300
  @dataclass(kw_only=True)
1082
1301
  class CESMBGCDataset(CESMDataset):
1083
- """Represents CESM BGC data on original grid.
1084
-
1085
- Parameters
1086
- ----------
1087
- filename : str
1088
- The path to the data files. Can contain wildcards.
1089
- start_time : Optional[datetime], optional
1090
- The start time for selecting relevant data. If not provided, the data is not filtered by start time.
1091
- end_time : Optional[datetime], optional
1092
- The end time for selecting relevant data. If not provided, only data at the start_time is selected if start_time is provided,
1093
- or no filtering is applied if start_time is not provided.
1094
- var_names: Dict[str, str], optional
1095
- Dictionary of variable names that are required in the dataset.
1096
- dim_names: Dict[str, str], optional
1097
- Dictionary specifying the names of dimensions in the dataset.
1098
- climatology : bool
1099
- Indicates whether the dataset is climatological. Defaults to False.
1100
-
1101
- Attributes
1102
- ----------
1103
- ds : xr.Dataset
1104
- The xarray Dataset containing the CESM data on its original grid.
1105
- """
1302
+ """Represents CESM BGC data on original grid."""
1106
1303
 
1107
1304
  var_names: Dict[str, str] = field(
1108
1305
  default_factory=lambda: {
@@ -1200,29 +1397,7 @@ class CESMBGCDataset(CESMDataset):
1200
1397
 
1201
1398
  @dataclass(kw_only=True)
1202
1399
  class CESMBGCSurfaceForcingDataset(CESMDataset):
1203
- """Represents CESM BGC surface forcing data on original grid.
1204
-
1205
- Parameters
1206
- ----------
1207
- filename : str
1208
- The path to the data files. Can contain wildcards.
1209
- start_time : Optional[datetime], optional
1210
- The start time for selecting relevant data. If not provided, the data is not filtered by start time.
1211
- end_time : Optional[datetime], optional
1212
- The end time for selecting relevant data. If not provided, only data at the start_time is selected if start_time is provided,
1213
- or no filtering is applied if start_time is not provided.
1214
- var_names: Dict[str, str], optional
1215
- Dictionary of variable names that are required in the dataset.
1216
- dim_names: Dict[str, str], optional
1217
- Dictionary specifying the names of dimensions in the dataset.
1218
- climatology : bool
1219
- Indicates whether the dataset is climatological. Defaults to False.
1220
-
1221
- Attributes
1222
- ----------
1223
- ds : xr.Dataset
1224
- The xarray Dataset containing the CESM data on its original grid.
1225
- """
1400
+ """Represents CESM BGC surface forcing data on original grid."""
1226
1401
 
1227
1402
  var_names: Dict[str, str] = field(
1228
1403
  default_factory=lambda: {
@@ -1269,29 +1444,7 @@ class CESMBGCSurfaceForcingDataset(CESMDataset):
1269
1444
 
1270
1445
  @dataclass(kw_only=True)
1271
1446
  class ERA5Dataset(Dataset):
1272
- """Represents ERA5 data on original grid.
1273
-
1274
- Parameters
1275
- ----------
1276
- filename : str
1277
- The path to the data files. Can contain wildcards.
1278
- start_time : Optional[datetime], optional
1279
- The start time for selecting relevant data. If not provided, the data is not filtered by start time.
1280
- end_time : Optional[datetime], optional
1281
- The end time for selecting relevant data. If not provided, only data at the start_time is selected if start_time is provided,
1282
- or no filtering is applied if start_time is not provided.
1283
- var_names: Dict[str, str], optional
1284
- Dictionary of variable names that are required in the dataset.
1285
- dim_names: Dict[str, str], optional
1286
- Dictionary specifying the names of dimensions in the dataset.
1287
- climatology : bool
1288
- Indicates whether the dataset is climatological. Defaults to False.
1289
-
1290
- Attributes
1291
- ----------
1292
- ds : xr.Dataset
1293
- The xarray Dataset containing the ERA5 data on its original grid.
1294
- """
1447
+ """Represents ERA5 data on original grid."""
1295
1448
 
1296
1449
  var_names: Dict[str, str] = field(
1297
1450
  default_factory=lambda: {
@@ -1389,27 +1542,10 @@ class ERA5Dataset(Dataset):
1389
1542
 
1390
1543
  @dataclass(kw_only=True)
1391
1544
  class ERA5Correction(Dataset):
1392
- """Global dataset to correct ERA5 radiation. The dataset contains multiplicative
1393
- correction factors for the ERA5 shortwave radiation, obtained by comparing the
1394
- COREv2 climatology to the ERA5 climatology.
1545
+ """Global dataset to correct ERA5 radiation.
1395
1546
 
1396
- Parameters
1397
- ----------
1398
- filename : str, optional
1399
- The path to the correction files. Defaults to download_correction_data('SSR_correction.nc').
1400
- var_names: Dict[str, str], optional
1401
- Dictionary of variable names that are required in the dataset.
1402
- Defaults to {"swr_corr": "ssr_corr"}.
1403
- dim_names: Dict[str, str], optional
1404
- Dictionary specifying the names of dimensions in the dataset.
1405
- Defaults to {"longitude": "longitude", "latitude": "latitude", "time": "time"}.
1406
- climatology : bool, optional
1407
- Indicates if the correction data is a climatology. Defaults to True.
1408
-
1409
- Attributes
1410
- ----------
1411
- ds : xr.Dataset
1412
- The loaded xarray Dataset containing the correction data.
1547
+ The dataset contains multiplicative correction factors for the ERA5 shortwave
1548
+ radiation, obtained by comparing the COREv2 climatology to the ERA5 climatology.
1413
1549
  """
1414
1550
 
1415
1551
  filename: str = field(
@@ -1429,8 +1565,6 @@ class ERA5Correction(Dataset):
1429
1565
  )
1430
1566
  climatology: Optional[bool] = True
1431
1567
 
1432
- ds: xr.Dataset = field(init=False, repr=False)
1433
-
1434
1568
  def __post_init__(self):
1435
1569
 
1436
1570
  if not self.climatology:
@@ -1494,27 +1628,7 @@ class ERA5Correction(Dataset):
1494
1628
 
1495
1629
  @dataclass(kw_only=True)
1496
1630
  class ETOPO5Dataset(Dataset):
1497
- """Represents topography data on the original grid from the ETOPO5 dataset.
1498
-
1499
- Parameters
1500
- ----------
1501
- filename : str, optional
1502
- The path to the ETOPO5 dataset file. If not provided, the dataset will be downloaded
1503
- automatically via the `pooch` library.
1504
- var_names : Dict[str, str], optional
1505
- Dictionary of variable names required in the dataset. Defaults to:
1506
- {
1507
- "topo": "topo",
1508
- }
1509
- dim_names : Dict[str, str], optional
1510
- Dictionary specifying the names of dimensions in the dataset. Defaults to:
1511
- {"longitude": "lon", "latitude": "lat"}.
1512
-
1513
- Attributes
1514
- ----------
1515
- ds : xr.Dataset
1516
- The xarray Dataset containing the ETOPO5 data, loaded from the specified file.
1517
- """
1631
+ """Represents topography data on the original grid from the ETOPO5 dataset."""
1518
1632
 
1519
1633
  filename: str = field(default_factory=lambda: download_topo("etopo5.nc"))
1520
1634
  var_names: Dict[str, str] = field(
@@ -1525,7 +1639,6 @@ class ETOPO5Dataset(Dataset):
1525
1639
  dim_names: Dict[str, str] = field(
1526
1640
  default_factory=lambda: {"longitude": "lon", "latitude": "lat"}
1527
1641
  )
1528
- ds: xr.Dataset = field(init=False, repr=False)
1529
1642
 
1530
1643
  def clean_up(self, ds: xr.Dataset) -> xr.Dataset:
1531
1644
  """Assign lat and lon as coordinates.
@@ -1551,28 +1664,8 @@ class ETOPO5Dataset(Dataset):
1551
1664
 
1552
1665
  @dataclass(kw_only=True)
1553
1666
  class SRTM15Dataset(Dataset):
1554
- """Represents topography data on the original grid from the SRTM15 dataset.
1667
+ """Represents topography data on the original grid from the SRTM15 dataset."""
1555
1668
 
1556
- Parameters
1557
- ----------
1558
- filename : str
1559
- The path to the SRTM15 dataset file.
1560
- var_names : Dict[str, str], optional
1561
- Dictionary of variable names required in the dataset. Defaults to:
1562
- {
1563
- "topo": "z",
1564
- }
1565
- dim_names : Dict[str, str], optional
1566
- Dictionary specifying the names of dimensions in the dataset. Defaults to:
1567
- {"longitude": "lon", "latitude": "lat"}.
1568
-
1569
- Attributes
1570
- ----------
1571
- ds : xr.Dataset
1572
- The xarray Dataset containing the SRTM15 data, loaded from the specified file.
1573
- """
1574
-
1575
- filename: str
1576
1669
  var_names: Dict[str, str] = field(
1577
1670
  default_factory=lambda: {
1578
1671
  "topo": "z",
@@ -1581,7 +1674,6 @@ class SRTM15Dataset(Dataset):
1581
1674
  dim_names: Dict[str, str] = field(
1582
1675
  default_factory=lambda: {"longitude": "lon", "latitude": "lat"}
1583
1676
  )
1584
- ds: xr.Dataset = field(init=False, repr=False)
1585
1677
 
1586
1678
 
1587
1679
  # river datasets
@@ -1962,37 +2054,11 @@ class RiverDataset:
1962
2054
 
1963
2055
  @dataclass(kw_only=True)
1964
2056
  class DaiRiverDataset(RiverDataset):
1965
- """Represents river data from the Dai river dataset.
1966
-
1967
- Parameters
1968
- ----------
1969
- filename : Union[str, Path, List[Union[str, Path]]], optional
1970
- The path to the Dai River dataset file. If not provided, the dataset will be downloaded
1971
- automatically via the `pooch` library.
1972
- start_time : datetime
1973
- The start time for selecting relevant data.
1974
- end_time : datetime
1975
- The end time for selecting relevant data.
1976
- dim_names: Dict[str, str], optional
1977
- Dictionary specifying the names of dimensions in the dataset.
1978
- var_names: Dict[str, str], optional
1979
- Dictionary of variable names that are required in the dataset.
1980
- opt_var_names: Dict[str, str], optional
1981
- Dictionary of variable names that are optional in the dataset.
1982
- climatology : bool
1983
- Indicates whether the dataset is climatological. Defaults to False.
1984
-
1985
- Attributes
1986
- ----------
1987
- ds : xr.Dataset
1988
- The xarray Dataset containing the forcing data on its original grid.
1989
- """
2057
+ """Represents river data from the Dai river dataset."""
1990
2058
 
1991
2059
  filename: Union[str, Path, List[Union[str, Path]]] = field(
1992
2060
  default_factory=lambda: download_river_data("dai_trenberth_may2019.nc")
1993
2061
  )
1994
- start_time: datetime
1995
- end_time: datetime
1996
2062
  dim_names: Dict[str, str] = field(
1997
2063
  default_factory=lambda: {
1998
2064
  "station": "station",
@@ -2014,7 +2080,6 @@ class DaiRiverDataset(RiverDataset):
2014
2080
  }
2015
2081
  )
2016
2082
  climatology: Optional[bool] = False
2017
- ds: xr.Dataset = field(init=False, repr=False)
2018
2083
 
2019
2084
  def add_time_info(self, ds: xr.Dataset) -> xr.Dataset:
2020
2085
  """Adds time information to the dataset based on the climatology flag and
@@ -2053,6 +2118,497 @@ class DaiRiverDataset(RiverDataset):
2053
2118
  return ds
2054
2119
 
2055
2120
 
2121
+ @dataclass
2122
+ class TPXOManager:
2123
+ """Manages multiple TPXODataset instances and selects and processes tidal
2124
+ constituents from the TPXO dataset.
2125
+
2126
+ This class handles multiple tidal constituents following the TPXO9v2a standard.
2127
+ The self-attraction and loading (SAL) correction data is sourced internally from TPXO9v2a.
2128
+
2129
+ Parameters
2130
+ ----------
2131
+ filenames : dict
2132
+ Dictionary containing paths to TPXO dataset files. Expected keys:
2133
+ - "h" : Path to the elevation file.
2134
+ - "u" : Path to the u-velocity component file.
2135
+ - "grid" : Path to the grid file.
2136
+
2137
+ ntides : int
2138
+ Number of tidal constituents to select for processing.
2139
+
2140
+ reference_date : datetime, optional
2141
+ Reference date for the TPXO data. Defaults to January 1, 1992.
2142
+ Used as the baseline for tidal time series calculations.
2143
+
2144
+ allan_factor : float, optional
2145
+ Factor used in tidal model computations. Defaults to 2.0.
2146
+
2147
+ use_dask : bool, optional
2148
+ Whether to use Dask for chunking. If True, data is loaded lazily; if False, data is loaded eagerly. Defaults to False.
2149
+
2150
+ Notes
2151
+ -----
2152
+ In TPXO products newer then 9v2a, the order of tidal constituents may change beyond the 10th constituent.
2153
+ Before selecting the first `ntides` constituents, newer products are reordered to match the TPXO9v2a standard.
2154
+ However, this reordering has minimal impact, as constituents beyond the 10th have negligible amplitudes.
2155
+ """
2156
+
2157
+ filenames: dict
2158
+ ntides: int
2159
+ reference_date: datetime = datetime(1992, 1, 1)
2160
+ allan_factor: float = 2.0
2161
+ use_dask: Optional[bool] = False
2162
+
2163
+ def __post_init__(self):
2164
+
2165
+ fname_sal = download_sal_data("sal_tpxo9.v2a.nc")
2166
+
2167
+ # Initialize the data_dict with TPXODataset instances
2168
+ data_dict = {
2169
+ "h": TPXODataset(
2170
+ filename=self.filenames["h"],
2171
+ grid_filename=self.filenames["grid"],
2172
+ location="h",
2173
+ var_names={"ssh_Re": "hRe", "ssh_Im": "hIm"},
2174
+ use_dask=self.use_dask,
2175
+ ),
2176
+ "sal": TPXODataset(
2177
+ filename=fname_sal,
2178
+ grid_filename=self.filenames["grid"],
2179
+ location="h",
2180
+ var_names={"sal_Re": "hRe", "sal_Im": "hIm"},
2181
+ use_dask=self.use_dask,
2182
+ tolerate_coord_mismatch=True, # Allow coordinate mismatch since SAL is from TPXO9v2a and may not align exactly with newer grids
2183
+ ),
2184
+ "u": TPXODataset(
2185
+ filename=self.filenames["u"],
2186
+ grid_filename=self.filenames["grid"],
2187
+ location="u",
2188
+ var_names={"u_Re": "URe", "u_Im": "UIm"},
2189
+ use_dask=self.use_dask,
2190
+ ),
2191
+ "v": TPXODataset(
2192
+ filename=self.filenames["u"],
2193
+ grid_filename=self.filenames["grid"],
2194
+ location="v",
2195
+ var_names={"v_Re": "VRe", "v_Im": "VIm"},
2196
+ use_dask=self.use_dask,
2197
+ ),
2198
+ }
2199
+
2200
+ omega = self.get_omega()
2201
+
2202
+ for data in data_dict.values():
2203
+ data.select_constituents(self.ntides, omega)
2204
+
2205
+ data_dict["omega"] = xr.DataArray(
2206
+ data=list(omega.values())[: self.ntides],
2207
+ dims="ntides",
2208
+ attrs={"long_name": "angular frequency", "units": "radians per second"},
2209
+ )
2210
+
2211
+ object.__setattr__(self, "datasets", data_dict)
2212
+
2213
+ def get_omega(self):
2214
+ """Retrieve angular frequencies (omega) for tidal constituents from the TPXO9.v2
2215
+ atlas.
2216
+
2217
+ This method returns the angular frequencies (in radians per second) for 15 tidal constituents,
2218
+ sourced from the TPXO tidal model and defined in the OTPSnc `constit.h` file, see https://www.tpxo.net/otps.
2219
+ These values are essential for tidal modeling and analysis.
2220
+
2221
+ Returns
2222
+ -------
2223
+ dict
2224
+ A dictionary where the keys are tidal constituent labels (str) and the values
2225
+ are their respective angular frequencies (float, in radians per second).
2226
+ """
2227
+ omega = {
2228
+ "m2": 1.405189e-04, # Principal lunar semidiurnal
2229
+ "s2": 1.454441e-04, # Principal solar semidiurnal
2230
+ "n2": 1.378797e-04, # Larger lunar elliptic semidiurnal
2231
+ "k2": 1.458423e-04, # Lunisolar semidiurnal
2232
+ "k1": 7.292117e-05, # Lunar diurnal
2233
+ "o1": 6.759774e-05, # Lunar diurnal
2234
+ "p1": 7.252295e-05, # Solar diurnal
2235
+ "q1": 6.495854e-05, # Larger lunar elliptic diurnal
2236
+ "mm": 0.026392e-04, # Lunar monthly
2237
+ "mf": 0.053234e-04, # Lunar fortnightly
2238
+ "m4": 2.810377e-04, # Shallow water overtide of M2
2239
+ "mn4": 2.783984e-04, # Shallow water quarter diurnal
2240
+ "ms4": 2.859630e-04, # Shallow water quarter diurnal
2241
+ "2n2": 1.352405e-04, # Shallow water semidiurnal
2242
+ "s1": 7.2722e-05, # Solar diurnal
2243
+ }
2244
+ return omega
2245
+
2246
+ def compute_equilibrium_tide(self, lon, lat):
2247
+ """Compute equilibrium tide for given longitudes and latitudes.
2248
+
2249
+ Parameters
2250
+ ----------
2251
+ lon : xr.DataArray
2252
+ Longitudes in degrees.
2253
+ lat : xr.DataArray
2254
+ Latitudes in degrees.
2255
+
2256
+ Returns
2257
+ -------
2258
+ tpc : xr.DataArray
2259
+ Equilibrium tide complex amplitude.
2260
+
2261
+ Notes
2262
+ -----
2263
+ This method calculates the equilibrium tide complex amplitude for specified
2264
+ longitudes and latitudes, considering 15 tidal constituents and their corresponding
2265
+ amplitudes and elasticity factors. The order of the tidal constituents corresponds
2266
+ to the order in `self.get_omega()`, which must remain consistent for future use.
2267
+
2268
+ The tidal constituents are categorized as follows:
2269
+ - **2**: Semidiurnal
2270
+ - **1**: Diurnal
2271
+ - **0**: Long-period
2272
+
2273
+ The amplitudes and elasticity factors are sourced from the `constit.h` file in the OTPSnc package.
2274
+ """
2275
+
2276
+ # Amplitudes for 15 tidal constituents (from variable amp_d in constit.h of OTPSnc package)
2277
+ A = xr.DataArray(
2278
+ data=np.array(
2279
+ [
2280
+ 0.242334, # M2
2281
+ 0.112743, # S2
2282
+ 0.046397, # N2
2283
+ 0.030684, # K2
2284
+ 0.141565, # K1
2285
+ 0.100661, # O1
2286
+ 0.046848, # P1
2287
+ 0.019273, # Q1
2288
+ 0.022191, # Mm
2289
+ 0.042041, # Mf
2290
+ 0.0, # M4
2291
+ 0.0, # Mn4
2292
+ 0.0, # Ms4
2293
+ 0.006141, # 2n2
2294
+ 0.000764, # S1
2295
+ ]
2296
+ ),
2297
+ dims="ntides",
2298
+ )
2299
+
2300
+ # Elasticity factors for 15 tidal constituents (from variable alpha_d in constit.h of OTPSnc package)
2301
+ B = xr.DataArray(
2302
+ data=np.array(
2303
+ [
2304
+ 0.693, # M2
2305
+ 0.693, # S2
2306
+ 0.693, # N2
2307
+ 0.693, # K2
2308
+ 0.736, # K1
2309
+ 0.695, # O1
2310
+ 0.706, # P1
2311
+ 0.695, # Q1
2312
+ 0.693, # Mm
2313
+ 0.693, # Mf
2314
+ 0.693, # M4
2315
+ 0.693, # Mn4
2316
+ 0.693, # Ms4
2317
+ 0.693, # 2n2
2318
+ 0.693, # S1
2319
+ ]
2320
+ ),
2321
+ dims="ntides",
2322
+ )
2323
+
2324
+ # Tidal type (from variable ispec_d in constit.h of OTPSnc package)
2325
+ # types: 2 = semidiurnal, 1 = diurnal, 0 = long-term
2326
+ ityp = xr.DataArray(
2327
+ data=np.array(
2328
+ [
2329
+ 2, # M2
2330
+ 2, # S2
2331
+ 2, # N2
2332
+ 2, # K2
2333
+ 1, # K1
2334
+ 1, # O1
2335
+ 1, # P1
2336
+ 1, # Q1
2337
+ 0, # Mm
2338
+ 0, # Mf
2339
+ 0, # M4
2340
+ 0, # Mn4
2341
+ 0, # Ms4
2342
+ 2, # 2n2
2343
+ 1, # S1
2344
+ ]
2345
+ ),
2346
+ dims="ntides",
2347
+ )
2348
+
2349
+ d2r = np.pi / 180
2350
+ coslat2 = np.cos(d2r * lat) ** 2
2351
+ sin2lat = np.sin(2 * d2r * lat)
2352
+
2353
+ p_amp = (
2354
+ xr.where(ityp == 2, 1, 0) * A * B * coslat2 # semidiurnal
2355
+ + xr.where(ityp == 1, 1, 0) * A * B * sin2lat # diurnal
2356
+ + xr.where(ityp == 0, 1, 0) * A * B * (0.5 - 1.5 * coslat2) # long-term
2357
+ )
2358
+ p_pha = (
2359
+ xr.where(ityp == 2, 1, 0) * (-2 * lon * d2r) # semidiurnal
2360
+ + xr.where(ityp == 1, 1, 0) * (-lon * d2r) # diurnal
2361
+ + xr.where(ityp == 0, 1, 0) * xr.zeros_like(lon) # long-term
2362
+ )
2363
+
2364
+ tpc = p_amp * np.exp(-1j * p_pha)
2365
+ tpc = tpc.isel(ntides=slice(None, self.ntides))
2366
+
2367
+ return tpc
2368
+
2369
+ def egbert_correction(self, date):
2370
+ """Correct phases and amplitudes for real-time runs using parts of the post-
2371
+ processing code from Egbert's & Erofeeva's (OSU) TPXO model.
2372
+
2373
+ Parameters
2374
+ ----------
2375
+ date : datetime.datetime
2376
+ The date and time for which corrections are to be applied.
2377
+
2378
+ Returns
2379
+ -------
2380
+ pf : xr.DataArray
2381
+ Amplitude scaling factor for each of the 15 tidal constituents.
2382
+ pu : xr.DataArray
2383
+ Phase correction [radians] for each of the 15 tidal constituents.
2384
+ aa : xr.DataArray
2385
+ Astronomical arguments [radians] associated with the corrections.
2386
+
2387
+ Notes
2388
+ -----
2389
+ The order of the tidal constituents corresponds
2390
+ to the order in `self.get_omega()`, which must remain consistent for future use.
2391
+
2392
+ References
2393
+ ----------
2394
+ - Egbert, G.D., and S.Y. Erofeeva. "Efficient inverse modeling of barotropic ocean
2395
+ tides." Journal of Atmospheric and Oceanic Technology 19, no. 2 (2002): 183-204.
2396
+ """
2397
+
2398
+ year = date.year
2399
+ month = date.month
2400
+ day = date.day
2401
+ hour = date.hour
2402
+ minute = date.minute
2403
+ second = date.second
2404
+
2405
+ rad = np.pi / 180.0
2406
+ deg = 180.0 / np.pi
2407
+ mjd = modified_julian_days(year, month, day)
2408
+ tstart = mjd + hour / 24 + minute / (60 * 24) + second / (60 * 60 * 24)
2409
+
2410
+ # Determine nodal corrections pu & pf : these expressions are valid for period 1990-2010 (Cartwright 1990).
2411
+ # Reset time origin for astronomical arguments to 4th of May 1860:
2412
+ timetemp = tstart - 51544.4993
2413
+
2414
+ # mean longitude of lunar perigee
2415
+ P = 83.3535 + 0.11140353 * timetemp
2416
+ P = np.mod(P, 360.0)
2417
+ if P < 0:
2418
+ P = +360
2419
+ P *= rad
2420
+
2421
+ # mean longitude of ascending lunar node
2422
+ N = 125.0445 - 0.05295377 * timetemp
2423
+ N = np.mod(N, 360.0)
2424
+ if N < 0:
2425
+ N = +360
2426
+ N *= rad
2427
+
2428
+ sinn = np.sin(N)
2429
+ cosn = np.cos(N)
2430
+ sin2n = np.sin(2 * N)
2431
+ cos2n = np.cos(2 * N)
2432
+ sin3n = np.sin(3 * N)
2433
+
2434
+ pftmp = np.sqrt(
2435
+ (1 - 0.03731 * cosn + 0.00052 * cos2n) ** 2
2436
+ + (0.03731 * sinn - 0.00052 * sin2n) ** 2
2437
+ )
2438
+
2439
+ pf = np.zeros(15)
2440
+ pf[0] = pftmp # M2
2441
+ pf[1] = 1.0 # S2
2442
+ pf[2] = pftmp # N2
2443
+ pf[3] = np.sqrt(
2444
+ (1 + 0.2852 * cosn + 0.0324 * cos2n) ** 2
2445
+ + (0.3108 * sinn + 0.0324 * sin2n) ** 2
2446
+ ) # K2
2447
+ pf[4] = np.sqrt(
2448
+ (1 + 0.1158 * cosn - 0.0029 * cos2n) ** 2
2449
+ + (0.1554 * sinn - 0.0029 * sin2n) ** 2
2450
+ ) # K1
2451
+ pf[5] = np.sqrt(
2452
+ (1 + 0.189 * cosn - 0.0058 * cos2n) ** 2
2453
+ + (0.189 * sinn - 0.0058 * sin2n) ** 2
2454
+ ) # O1
2455
+ pf[6] = 1.0 # P1
2456
+ pf[7] = np.sqrt((1 + 0.188 * cosn) ** 2 + (0.188 * sinn) ** 2) # Q1
2457
+ pf[8] = 1.0 - 0.130 * cosn # Mm
2458
+ pf[9] = 1.043 + 0.414 * cosn # Mf
2459
+ pf[10] = pftmp**2 # M4
2460
+ pf[11] = pftmp**2 # Mn4
2461
+ pf[12] = pftmp**2 # Ms4
2462
+ pf[13] = pftmp # 2n2
2463
+ pf[14] = 1.0 # S1
2464
+ pf = xr.DataArray(pf, dims="ntides")
2465
+
2466
+ putmp = (
2467
+ np.arctan(
2468
+ (-0.03731 * sinn + 0.00052 * sin2n)
2469
+ / (1.0 - 0.03731 * cosn + 0.00052 * cos2n)
2470
+ )
2471
+ * deg
2472
+ )
2473
+
2474
+ pu = np.zeros(15)
2475
+ pu[0] = putmp # M2
2476
+ pu[1] = 0.0 # S2
2477
+ pu[2] = putmp # N2
2478
+ pu[3] = (
2479
+ np.arctan(
2480
+ -(0.3108 * sinn + 0.0324 * sin2n)
2481
+ / (1.0 + 0.2852 * cosn + 0.0324 * cos2n)
2482
+ )
2483
+ * deg
2484
+ ) # K2
2485
+ pu[4] = (
2486
+ np.arctan(
2487
+ (-0.1554 * sinn + 0.0029 * sin2n)
2488
+ / (1.0 + 0.1158 * cosn - 0.0029 * cos2n)
2489
+ )
2490
+ * deg
2491
+ ) # K1
2492
+ pu[5] = 10.8 * sinn - 1.3 * sin2n + 0.2 * sin3n # O1
2493
+ pu[6] = 0.0 # P1
2494
+ pu[7] = np.arctan(0.189 * sinn / (1.0 + 0.189 * cosn)) * deg # Q1
2495
+ pu[8] = 0.0 # Mm
2496
+ pu[9] = -23.7 * sinn + 2.7 * sin2n - 0.4 * sin3n # Mf
2497
+ pu[10] = putmp * 2.0 # M4
2498
+ pu[11] = putmp * 2.0 # Mn4
2499
+ pu[12] = putmp # Ms4
2500
+ pu[13] = putmp # 2n2
2501
+ pu[14] = 0.0 # S1
2502
+ pu = xr.DataArray(pu, dims="ntides")
2503
+ # convert from degrees to radians
2504
+ pu = pu * rad
2505
+
2506
+ aa = xr.DataArray(
2507
+ data=np.array(
2508
+ [
2509
+ 1.731557546, # M2
2510
+ 0.0, # S2
2511
+ 6.050721243, # N2
2512
+ 3.487600001, # K2
2513
+ 0.173003674, # K1
2514
+ 1.558553872, # O1
2515
+ 6.110181633, # P1
2516
+ 5.877717569, # Q1
2517
+ 1.964021610, # Mm
2518
+ 1.756042456, # Mf
2519
+ 3.463115091, # M4
2520
+ 1.499093481, # Mn4
2521
+ 1.731557546, # Ms4
2522
+ 4.086699633, # 2n2
2523
+ 0.0, # S1
2524
+ ]
2525
+ ),
2526
+ dims="ntides",
2527
+ )
2528
+ pf = pf.isel(ntides=slice(None, self.ntides))
2529
+ pu = pu.isel(ntides=slice(None, self.ntides))
2530
+ aa = aa.isel(ntides=slice(None, self.ntides))
2531
+
2532
+ return pf, pu, aa
2533
+
2534
+ def correct_tides(self, model_reference_date):
2535
+ """Apply tidal corrections to the dataset. This method corrects the dataset for
2536
+ equilibrium tides, self-attraction and loading (SAL) effects, and adjusts phases
2537
+ and amplitudes of tidal elevations and transports using Egbert's correction.
2538
+
2539
+ Parameters
2540
+ ----------
2541
+ model_reference_date : datetime
2542
+ The reference date for the ROMS simulation.
2543
+
2544
+ Returns
2545
+ -------
2546
+ None
2547
+ The dataset is modified in-place with corrected real and imaginary components for ssh, u, v, and the
2548
+ potential field ('pot_Re', 'pot_Im').
2549
+ """
2550
+
2551
+ datasets = self.datasets
2552
+ omega = self.datasets["omega"].isel(ntides=slice(None, self.ntides))
2553
+
2554
+ # Get equilibrium tides
2555
+ lon = datasets["sal"].ds[datasets["sal"].dim_names["longitude"]]
2556
+ lat = datasets["sal"].ds[datasets["sal"].dim_names["latitude"]]
2557
+ tpc = self.compute_equilibrium_tide(lon, lat)
2558
+
2559
+ # Correct for SAL
2560
+ tsc = self.allan_factor * (
2561
+ datasets["sal"].ds[datasets["sal"].var_names["sal_Re"]]
2562
+ + 1j * datasets["sal"].ds[datasets["sal"].var_names["sal_Im"]]
2563
+ )
2564
+ tpc = tpc - tsc
2565
+
2566
+ # Elevations and transports
2567
+ thc = (
2568
+ datasets["h"].ds[datasets["h"].var_names["ssh_Re"]]
2569
+ + 1j * datasets["h"].ds[datasets["h"].var_names["ssh_Im"]]
2570
+ )
2571
+ tuc = (
2572
+ datasets["u"].ds[datasets["u"].var_names["u_Re"]]
2573
+ + 1j * datasets["u"].ds[datasets["u"].var_names["u_Im"]]
2574
+ )
2575
+ tvc = (
2576
+ datasets["v"].ds[datasets["v"].var_names["v_Re"]]
2577
+ + 1j * datasets["v"].ds[datasets["v"].var_names["v_Im"]]
2578
+ )
2579
+
2580
+ # Apply correction for phases and amplitudes
2581
+ pf, pu, aa = self.egbert_correction(model_reference_date)
2582
+
2583
+ dt = (model_reference_date - self.reference_date).days * 3600 * 24
2584
+
2585
+ thc = pf * thc * np.exp(1j * (omega * dt + pu + aa))
2586
+ tuc = pf * tuc * np.exp(1j * (omega * dt + pu + aa))
2587
+ tvc = pf * tvc * np.exp(1j * (omega * dt + pu + aa))
2588
+ tpc = pf * tpc * np.exp(1j * (omega * dt + pu + aa))
2589
+
2590
+ datasets["h"].ds[datasets["h"].var_names["ssh_Re"]] = thc.real
2591
+ datasets["h"].ds[datasets["h"].var_names["ssh_Im"]] = thc.imag
2592
+ datasets["u"].ds[datasets["u"].var_names["u_Re"]] = tuc.real
2593
+ datasets["u"].ds[datasets["u"].var_names["u_Im"]] = tuc.imag
2594
+ datasets["v"].ds[datasets["v"].var_names["v_Re"]] = tvc.real
2595
+ datasets["v"].ds[datasets["v"].var_names["v_Im"]] = tvc.imag
2596
+ datasets["sal"].ds["pot_Re"] = tpc.real
2597
+ datasets["sal"].ds["pot_Im"] = tpc.imag
2598
+
2599
+ object.__setattr__(self, "datasets", datasets)
2600
+
2601
+ # Update var_names dictionary
2602
+ var_names = {
2603
+ **datasets["sal"].var_names,
2604
+ "pot_Re": "pot_Re",
2605
+ "pot_Im": "pot_Im",
2606
+ }
2607
+ var_names.pop("sal_Re", None) # Remove "sal_Re" if it exists
2608
+ var_names.pop("sal_Im", None) # Remove "sal_Im" if it exists
2609
+ object.__setattr__(self.datasets["sal"], "var_names", var_names)
2610
+
2611
+
2056
2612
  # shared functions
2057
2613
 
2058
2614
 
@@ -2168,8 +2724,9 @@ def _select_relevant_times(
2168
2724
  f"The dataset contains {len(ds[time_dim])} time steps, but the climatology flag is set to True, which requires exactly 12 time steps."
2169
2725
  )
2170
2726
  if not end_time:
2727
+ # Convert from timedelta64[ns] to fractional days
2728
+ ds["time"] = ds["time"] / np.timedelta64(1, "D")
2171
2729
  # Interpolate from climatology for initial conditions
2172
- ds["time"] = ds["time"].dt.days
2173
2730
  ds = interpolate_from_climatology(ds, time_dim, start_time)
2174
2731
  else:
2175
2732
  time_type = get_time_type(ds[time_dim])
@@ -2254,3 +2811,61 @@ def decode_string(byte_array):
2254
2811
  )
2255
2812
 
2256
2813
  return decoded_string
2814
+
2815
+
2816
+ def modified_julian_days(year, month, day, hour=0):
2817
+ """Calculate the Modified Julian Day (MJD) for a given date and time.
2818
+
2819
+ The Modified Julian Day (MJD) is a modified Julian day count starting from
2820
+ November 17, 1858 AD. It is commonly used in astronomy and geodesy.
2821
+
2822
+ Parameters
2823
+ ----------
2824
+ year : int
2825
+ The year.
2826
+ month : int
2827
+ The month (1-12).
2828
+ day : int
2829
+ The day of the month.
2830
+ hour : float, optional
2831
+ The hour of the day as a fractional number (0 to 23.999...). Default is 0.
2832
+
2833
+ Returns
2834
+ -------
2835
+ mjd : float
2836
+ The Modified Julian Day (MJD) corresponding to the input date and time.
2837
+
2838
+ Notes
2839
+ -----
2840
+ The algorithm assumes that the input date (year, month, day) is within the
2841
+ Gregorian calendar, i.e., after October 15, 1582. Negative MJD values are
2842
+ allowed for dates before November 17, 1858.
2843
+
2844
+ References
2845
+ ----------
2846
+ - Wikipedia article on Julian Day: https://en.wikipedia.org/wiki/Julian_day
2847
+ - Wikipedia article on Modified Julian Day: https://en.wikipedia.org/wiki/Modified_Julian_day
2848
+
2849
+ Examples
2850
+ --------
2851
+ >>> modified_julian_days(2024, 5, 20, 12)
2852
+ 58814.0
2853
+ >>> modified_julian_days(1858, 11, 17)
2854
+ 0.0
2855
+ >>> modified_julian_days(1582, 10, 4)
2856
+ -141428.5
2857
+ """
2858
+
2859
+ if month < 3:
2860
+ year -= 1
2861
+ month += 12
2862
+
2863
+ A = year // 100
2864
+ B = A // 4
2865
+ C = 2 - A + B
2866
+ E = int(365.25 * (year + 4716))
2867
+ F = int(30.6001 * (month + 1))
2868
+ jd = C + day + hour / 24 + E + F - 1524.5
2869
+ mjd = jd - 2400000.5
2870
+
2871
+ return mjd