roms-tools 3.2.0__py3-none-any.whl → 3.4.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 (318) hide show
  1. roms_tools/__init__.py +1 -1
  2. roms_tools/analysis/cdr_ensemble.py +10 -13
  3. roms_tools/analysis/roms_output.py +5 -304
  4. roms_tools/{download.py → datasets/download.py} +1 -0
  5. roms_tools/{setup/datasets.py → datasets/lat_lon_datasets.py} +85 -854
  6. roms_tools/datasets/river_datasets.py +532 -0
  7. roms_tools/datasets/roms_dataset.py +767 -0
  8. roms_tools/datasets/utils.py +475 -0
  9. roms_tools/{setup/fill.py → fill.py} +110 -13
  10. roms_tools/plot.py +42 -34
  11. roms_tools/setup/boundary_forcing.py +52 -44
  12. roms_tools/setup/cdr_release.py +2 -4
  13. roms_tools/setup/grid.py +42 -17
  14. roms_tools/setup/initial_conditions.py +23 -23
  15. roms_tools/setup/nesting.py +270 -94
  16. roms_tools/setup/river_forcing.py +5 -5
  17. roms_tools/setup/surface_forcing.py +17 -12
  18. roms_tools/setup/tides.py +1 -1
  19. roms_tools/setup/topography.py +13 -7
  20. roms_tools/setup/utils.py +103 -294
  21. roms_tools/tests/test_analysis/test_cdr_ensemble.py +4 -6
  22. roms_tools/tests/test_analysis/test_roms_output.py +1 -220
  23. roms_tools/tests/{test_setup/test_datasets.py → test_datasets/test_lat_lon_datasets.py} +25 -64
  24. roms_tools/tests/test_datasets/test_river_datasets.py +48 -0
  25. roms_tools/tests/test_datasets/test_roms_dataset.py +539 -0
  26. roms_tools/tests/test_datasets/test_utils.py +527 -0
  27. roms_tools/tests/{test_setup/test_fill.py → test_fill.py} +72 -9
  28. roms_tools/tests/test_setup/test_boundary_forcing.py +57 -138
  29. roms_tools/tests/test_setup/test_cdr_release.py +4 -5
  30. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_east/c/0/0/0 +0 -0
  31. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_north/c/0/0/0 +0 -0
  32. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_east/c/0/0/0 +0 -0
  33. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_north/c/0/0/0 +0 -0
  34. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_east/c/0/0/0 +0 -0
  35. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_north/c/0/0/0 +0 -0
  36. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_east/c/0/0/0 +0 -0
  37. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_north/c/0/0/0 +0 -0
  38. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_east/c/0/0/0 +0 -0
  39. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_north/c/0/0/0 +0 -0
  40. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_east/c/0/0/0 +0 -0
  41. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_north/c/0/0/0 +0 -0
  42. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_east/c/0/0/0 +0 -0
  43. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_north/c/0/0/0 +0 -0
  44. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_east/c/0/0/0 +0 -0
  45. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_north/c/0/0/0 +0 -0
  46. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_east/c/0/0/0 +0 -0
  47. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_north/c/0/0/0 +0 -0
  48. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_east/c/0/0/0 +0 -0
  49. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_north/c/0/0/0 +0 -0
  50. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_east/c/0/0/0 +0 -0
  51. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_north/c/0/0/0 +0 -0
  52. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_east/c/0/0/0 +0 -0
  53. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_north/c/0/0/0 +0 -0
  54. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_east/c/0/0/0 +0 -0
  55. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_north/c/0/0/0 +0 -0
  56. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_east/c/0/0/0 +0 -0
  57. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_north/c/0/0/0 +0 -0
  58. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_east/c/0/0/0 +0 -0
  59. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_north/c/0/0/0 +0 -0
  60. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_east/c/0/0/0 +0 -0
  61. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_north/c/0/0/0 +0 -0
  62. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_east/c/0/0/0 +0 -0
  63. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_north/c/0/0/0 +0 -0
  64. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_east/c/0/0/0 +0 -0
  65. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_north/c/0/0/0 +0 -0
  66. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_east/c/0/0/0 +0 -0
  67. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_north/c/0/0/0 +0 -0
  68. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_east/c/0/0/0 +0 -0
  69. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_north/c/0/0/0 +0 -0
  70. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_east/c/0/0/0 +0 -0
  71. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_north/c/0/0/0 +0 -0
  72. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_east/c/0/0/0 +0 -0
  73. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_north/c/0/0/0 +0 -0
  74. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_east/c/0/0/0 +0 -0
  75. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_north/c/0/0/0 +0 -0
  76. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_east/c/0/0/0 +0 -0
  77. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_north/c/0/0/0 +0 -0
  78. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_east/c/0/0/0 +0 -0
  79. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_north/c/0/0/0 +0 -0
  80. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_east/c/0/0/0 +0 -0
  81. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_north/c/0/0/0 +0 -0
  82. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_east/c/0/0/0 +0 -0
  83. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_north/c/0/0/0 +0 -0
  84. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_east/c/0/0/0 +0 -0
  85. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_north/c/0/0/0 +0 -0
  86. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_east/c/0/0/0 +0 -0
  87. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_north/c/0/0/0 +0 -0
  88. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_east/c/0/0/0 +0 -0
  89. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_north/c/0/0/0 +0 -0
  90. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_east/c/0/0/0 +0 -0
  91. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_north/c/0/0/0 +0 -0
  92. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zarr.json +289 -2017
  93. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_east/c/0/0/0 +0 -0
  94. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_north/c/0/0/0 +0 -0
  95. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zarr.json +294 -2022
  96. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_east/c/0/0/0 +0 -0
  97. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_north/c/0/0/0 +0 -0
  98. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_south/c/0/0/0 +0 -0
  99. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/salt_west/c/0/0/0 +0 -0
  100. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_east/c/0/0/0 +0 -0
  101. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_north/c/0/0/0 +0 -0
  102. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_south/c/0/0/0 +0 -0
  103. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/temp_west/c/0/0/0 +0 -0
  104. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_east/c/0/0/0 +0 -0
  105. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_north/c/0/0/0 +0 -0
  106. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_south/c/0/0/0 +0 -0
  107. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/u_west/c/0/0/0 +0 -0
  108. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_east/c/0/0 +0 -0
  109. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_north/c/0/0 +0 -0
  110. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_south/c/0/0 +0 -0
  111. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/ubar_west/c/0/0 +0 -0
  112. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_east/c/0/0/0 +0 -0
  113. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_north/c/0/0/0 +0 -0
  114. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_south/c/0/0/0 +0 -0
  115. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/v_west/c/0/0/0 +0 -0
  116. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_east/c/0/0 +0 -0
  117. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_north/c/0/0 +0 -0
  118. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_south/c/0/0 +0 -0
  119. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/vbar_west/c/0/0 +0 -0
  120. roms_tools/tests/test_setup/test_data/boundary_forcing.zarr/zarr.json +182 -182
  121. roms_tools/tests/test_setup/test_data/grid.zarr/h/c/0/0 +0 -0
  122. roms_tools/tests/test_setup/test_data/grid.zarr/zarr.json +191 -191
  123. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/h/c/0/0 +0 -0
  124. roms_tools/tests/test_setup/test_data/grid_that_straddles_dateline.zarr/zarr.json +210 -210
  125. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK/c/0/0/0/0 +0 -0
  126. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ALK_ALT_CO2/c/0/0/0/0 +0 -0
  127. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC/c/0/0/0/0 +0 -0
  128. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DIC_ALT_CO2/c/0/0/0/0 +0 -0
  129. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOC/c/0/0/0/0 +0 -0
  130. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOCr/c/0/0/0/0 +0 -0
  131. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DON/c/0/0/0/0 +0 -0
  132. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DONr/c/0/0/0/0 +0 -0
  133. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOP/c/0/0/0/0 +0 -0
  134. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/DOPr/c/0/0/0/0 +0 -0
  135. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Fe/c/0/0/0/0 +0 -0
  136. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/Lig/c/0/0/0/0 +0 -0
  137. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NH4/c/0/0/0/0 +0 -0
  138. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/NO3/c/0/0/0/0 +0 -0
  139. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/O2/c/0/0/0/0 +0 -0
  140. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/PO4/c/0/0/0/0 +0 -0
  141. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/SiO3/c/0/0/0/0 +0 -0
  142. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatC/c/0/0/0/0 +0 -0
  143. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatChl/c/0/0/0/0 +0 -0
  144. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatFe/c/0/0/0/0 +0 -0
  145. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatP/c/0/0/0/0 +0 -0
  146. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diatSi/c/0/0/0/0 +0 -0
  147. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazC/c/0/0/0/0 +0 -0
  148. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazChl/c/0/0/0/0 +0 -0
  149. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazFe/c/0/0/0/0 +0 -0
  150. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/diazP/c/0/0/0/0 +0 -0
  151. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/salt/c/0/0/0/0 +0 -0
  152. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spC/c/0/0/0/0 +0 -0
  153. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spCaCO3/c/0/0/0/0 +0 -0
  154. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spChl/c/0/0/0/0 +0 -0
  155. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spFe/c/0/0/0/0 +0 -0
  156. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/spP/c/0/0/0/0 +0 -0
  157. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/temp/c/0/0/0/0 +0 -0
  158. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/u/c/0/0/0/0 +0 -0
  159. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/ubar/c/0/0/0 +0 -0
  160. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/v/c/0/0/0/0 +0 -0
  161. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/vbar/c/0/0/0 +0 -0
  162. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zarr.json +182 -182
  163. roms_tools/tests/test_setup/test_data/initial_conditions_with_bgc_from_climatology.zarr/zooC/c/0/0/0/0 +0 -0
  164. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/salt/c/0/0/0/0 +0 -0
  165. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/temp/c/0/0/0/0 +0 -0
  166. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/u/c/0/0/0/0 +0 -0
  167. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/ubar/c/0/0/0 +0 -0
  168. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/v/c/0/0/0/0 +0 -0
  169. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/vbar/c/0/0/0 +0 -0
  170. roms_tools/tests/test_setup/test_data/initial_conditions_with_unified_bgc_from_climatology.zarr/zarr.json +187 -187
  171. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Im/c/0/0/0 +0 -0
  172. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/u_Re/c/0/0/0 +0 -0
  173. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Im/c/0/0/0 +0 -0
  174. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/v_Re/c/0/0/0 +0 -0
  175. roms_tools/tests/test_setup/test_data/tidal_forcing.zarr/zarr.json +66 -66
  176. roms_tools/tests/test_setup/test_grid.py +56 -1
  177. roms_tools/tests/test_setup/test_initial_conditions.py +3 -94
  178. roms_tools/tests/test_setup/test_nesting.py +119 -30
  179. roms_tools/tests/test_setup/test_surface_forcing.py +2 -2
  180. roms_tools/tests/test_setup/test_tides.py +1 -1
  181. roms_tools/tests/test_setup/test_utils.py +100 -15
  182. roms_tools/tests/test_tiling/test_partition.py +63 -15
  183. roms_tools/tests/test_utils.py +78 -0
  184. roms_tools/tiling/partition.py +81 -211
  185. roms_tools/utils.py +193 -0
  186. {roms_tools-3.2.0.dist-info → roms_tools-3.4.0.dist-info}/METADATA +1 -1
  187. {roms_tools-3.2.0.dist-info → roms_tools-3.4.0.dist-info}/RECORD +190 -312
  188. {roms_tools-3.2.0.dist-info → roms_tools-3.4.0.dist-info}/WHEEL +1 -1
  189. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/c/0/0/0 +0 -0
  190. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_ALT_CO2_west/zarr.json +0 -54
  191. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/c/0/0/0 +0 -0
  192. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/ALK_west/zarr.json +0 -54
  193. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/c/0/0/0 +0 -0
  194. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_ALT_CO2_west/zarr.json +0 -54
  195. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/c/0/0/0 +0 -0
  196. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DIC_west/zarr.json +0 -54
  197. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/c/0/0/0 +0 -0
  198. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOC_west/zarr.json +0 -54
  199. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/c/0/0/0 +0 -0
  200. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOCr_west/zarr.json +0 -54
  201. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/c/0/0/0 +0 -0
  202. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DON_west/zarr.json +0 -54
  203. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/c/0/0/0 +0 -0
  204. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DONr_west/zarr.json +0 -54
  205. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/c/0/0/0 +0 -0
  206. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOP_west/zarr.json +0 -54
  207. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/c/0/0/0 +0 -0
  208. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/DOPr_west/zarr.json +0 -54
  209. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/c/0/0/0 +0 -0
  210. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Fe_west/zarr.json +0 -54
  211. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/c/0/0/0 +0 -0
  212. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/Lig_west/zarr.json +0 -54
  213. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/c/0/0/0 +0 -0
  214. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NH4_west/zarr.json +0 -54
  215. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/c/0/0/0 +0 -0
  216. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/NO3_west/zarr.json +0 -54
  217. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/c/0/0/0 +0 -0
  218. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/O2_west/zarr.json +0 -54
  219. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/c/0/0/0 +0 -0
  220. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/PO4_west/zarr.json +0 -54
  221. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/c/0/0/0 +0 -0
  222. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/SiO3_west/zarr.json +0 -54
  223. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/c/0/0/0 +0 -0
  224. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatC_west/zarr.json +0 -54
  225. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/c/0/0/0 +0 -0
  226. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatChl_west/zarr.json +0 -54
  227. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/c/0/0/0 +0 -0
  228. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatFe_west/zarr.json +0 -54
  229. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/c/0/0/0 +0 -0
  230. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatP_west/zarr.json +0 -54
  231. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/c/0/0/0 +0 -0
  232. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diatSi_west/zarr.json +0 -54
  233. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/c/0/0/0 +0 -0
  234. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazC_west/zarr.json +0 -54
  235. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/c/0/0/0 +0 -0
  236. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazChl_west/zarr.json +0 -54
  237. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/c/0/0/0 +0 -0
  238. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazFe_west/zarr.json +0 -54
  239. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/c/0/0/0 +0 -0
  240. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/diazP_west/zarr.json +0 -54
  241. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/c/0/0/0 +0 -0
  242. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spC_west/zarr.json +0 -54
  243. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/c/0/0/0 +0 -0
  244. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spCaCO3_west/zarr.json +0 -54
  245. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/c/0/0/0 +0 -0
  246. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spChl_west/zarr.json +0 -54
  247. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/c/0/0/0 +0 -0
  248. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spFe_west/zarr.json +0 -54
  249. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/c/0/0/0 +0 -0
  250. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/spP_west/zarr.json +0 -54
  251. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/c/0/0/0 +0 -0
  252. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_climatology.zarr/zooC_west/zarr.json +0 -54
  253. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_west/c/0/0/0 +0 -0
  254. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_ALT_CO2_west/zarr.json +0 -54
  255. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_west/c/0/0/0 +0 -0
  256. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/ALK_west/zarr.json +0 -54
  257. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_west/c/0/0/0 +0 -0
  258. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_ALT_CO2_west/zarr.json +0 -54
  259. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_west/c/0/0/0 +0 -0
  260. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DIC_west/zarr.json +0 -54
  261. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_west/c/0/0/0 +0 -0
  262. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOC_west/zarr.json +0 -54
  263. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_west/c/0/0/0 +0 -0
  264. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOCr_west/zarr.json +0 -54
  265. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_west/c/0/0/0 +0 -0
  266. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DON_west/zarr.json +0 -54
  267. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_west/c/0/0/0 +0 -0
  268. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DONr_west/zarr.json +0 -54
  269. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_west/c/0/0/0 +0 -0
  270. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOP_west/zarr.json +0 -54
  271. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_west/c/0/0/0 +0 -0
  272. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/DOPr_west/zarr.json +0 -54
  273. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_west/c/0/0/0 +0 -0
  274. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Fe_west/zarr.json +0 -54
  275. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_west/c/0/0/0 +0 -0
  276. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/Lig_west/zarr.json +0 -54
  277. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_west/c/0/0/0 +0 -0
  278. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NH4_west/zarr.json +0 -54
  279. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_west/c/0/0/0 +0 -0
  280. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/NO3_west/zarr.json +0 -54
  281. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_west/c/0/0/0 +0 -0
  282. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/O2_west/zarr.json +0 -54
  283. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_west/c/0/0/0 +0 -0
  284. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/PO4_west/zarr.json +0 -54
  285. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_west/c/0/0/0 +0 -0
  286. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/SiO3_west/zarr.json +0 -54
  287. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_west/c/0/0/0 +0 -0
  288. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatC_west/zarr.json +0 -54
  289. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_west/c/0/0/0 +0 -0
  290. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatChl_west/zarr.json +0 -54
  291. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_west/c/0/0/0 +0 -0
  292. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatFe_west/zarr.json +0 -54
  293. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_west/c/0/0/0 +0 -0
  294. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatP_west/zarr.json +0 -54
  295. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_west/c/0/0/0 +0 -0
  296. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diatSi_west/zarr.json +0 -54
  297. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_west/c/0/0/0 +0 -0
  298. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazC_west/zarr.json +0 -54
  299. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_west/c/0/0/0 +0 -0
  300. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazChl_west/zarr.json +0 -54
  301. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_west/c/0/0/0 +0 -0
  302. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazFe_west/zarr.json +0 -54
  303. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_west/c/0/0/0 +0 -0
  304. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/diazP_west/zarr.json +0 -54
  305. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_west/c/0/0/0 +0 -0
  306. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spC_west/zarr.json +0 -54
  307. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_west/c/0/0/0 +0 -0
  308. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spCaCO3_west/zarr.json +0 -54
  309. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_west/c/0/0/0 +0 -0
  310. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spChl_west/zarr.json +0 -54
  311. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_west/c/0/0/0 +0 -0
  312. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spFe_west/zarr.json +0 -54
  313. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_west/c/0/0/0 +0 -0
  314. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/spP_west/zarr.json +0 -54
  315. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_west/c/0/0/0 +0 -0
  316. roms_tools/tests/test_setup/test_data/bgc_boundary_forcing_from_unified_climatology.zarr/zooC_west/zarr.json +0 -54
  317. {roms_tools-3.2.0.dist-info → roms_tools-3.4.0.dist-info}/licenses/LICENSE +0 -0
  318. {roms_tools-3.2.0.dist-info → roms_tools-3.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,532 @@
1
+ import logging
2
+ from collections import Counter, defaultdict
3
+ from dataclasses import dataclass, field
4
+ from datetime import datetime
5
+ from pathlib import Path
6
+
7
+ import numpy as np
8
+ import xarray as xr
9
+
10
+ from roms_tools.datasets.download import download_river_data
11
+ from roms_tools.datasets.utils import check_dataset, select_relevant_times
12
+ from roms_tools.setup.utils import (
13
+ assign_dates_to_climatology,
14
+ gc_dist,
15
+ )
16
+ from roms_tools.utils import load_data
17
+
18
+
19
+ @dataclass(kw_only=True)
20
+ class RiverDataset:
21
+ """Represents river data.
22
+
23
+ Parameters
24
+ ----------
25
+ filename : Union[str, Path, List[Union[str, Path]]]
26
+ The path to the data file(s). Can be a single string (with or without wildcards), a single Path object,
27
+ or a list of strings or Path objects containing multiple files.
28
+ start_time : datetime
29
+ The start time for selecting relevant data.
30
+ end_time : datetime
31
+ The end time for selecting relevant data.
32
+ dim_names: Dict[str, str]
33
+ Dictionary specifying the names of dimensions in the dataset.
34
+ Requires "station" and "time" as keys.
35
+ var_names: Dict[str, str]
36
+ Dictionary of variable names that are required in the dataset.
37
+ Requires the keys "latitude", "longitude", "flux", "ratio", and "name".
38
+ opt_var_names: Dict[str, str], optional
39
+ Dictionary of variable names that are optional in the dataset.
40
+ Defaults to an empty dictionary.
41
+ climatology : bool
42
+ Indicates whether the dataset is climatological. Defaults to False.
43
+
44
+ Attributes
45
+ ----------
46
+ ds : xr.Dataset
47
+ The xarray Dataset containing the forcing data on its original grid.
48
+ """
49
+
50
+ filename: str | Path | list[str | Path]
51
+ start_time: datetime
52
+ end_time: datetime
53
+ dim_names: dict[str, str]
54
+ var_names: dict[str, str]
55
+ opt_var_names: dict[str, str] | None = field(default_factory=dict)
56
+ climatology: bool = False
57
+ ds: xr.Dataset = field(init=False, repr=False)
58
+
59
+ def __post_init__(self):
60
+ # Validate start_time and end_time
61
+ if not isinstance(self.start_time, datetime):
62
+ raise TypeError(
63
+ f"start_time must be a datetime object, but got {type(self.start_time).__name__}."
64
+ )
65
+ if not isinstance(self.end_time, datetime):
66
+ raise TypeError(
67
+ f"end_time must be a datetime object, but got {type(self.end_time).__name__}."
68
+ )
69
+
70
+ ds = self.load_data()
71
+ ds = self.clean_up(ds)
72
+ self.check_dataset(ds)
73
+ ds = _deduplicate_river_names(
74
+ ds, self.var_names["name"], self.dim_names["station"]
75
+ )
76
+
77
+ # Select relevant times
78
+ ds = self.add_time_info(ds)
79
+ self.ds = ds
80
+
81
+ def load_data(self) -> xr.Dataset:
82
+ """Load dataset from the specified file.
83
+
84
+ Returns
85
+ -------
86
+ ds : xr.Dataset
87
+ The loaded xarray Dataset containing the forcing data.
88
+ """
89
+ ds = load_data(
90
+ self.filename, self.dim_names, use_dask=False, decode_times=False
91
+ )
92
+
93
+ return ds
94
+
95
+ def clean_up(self, ds: xr.Dataset) -> xr.Dataset:
96
+ """Decodes the 'name' variable (if byte-encoded) and updates the dataset.
97
+
98
+ This method checks if the 'name' variable is of dtype 'object' (i.e., byte-encoded),
99
+ and if so, decodes each byte array to a string and updates the dataset.
100
+ It also ensures that the 'station' dimension is of integer type.
101
+
102
+
103
+ Parameters
104
+ ----------
105
+ ds : xr.Dataset
106
+ The dataset containing the 'name' variable to decode.
107
+
108
+ Returns
109
+ -------
110
+ ds : xr.Dataset
111
+ The dataset with the decoded 'name' variable.
112
+ """
113
+ if ds[self.var_names["name"]].dtype == "object":
114
+ names = []
115
+ for i in range(len(ds[self.dim_names["station"]])):
116
+ byte_array = ds[self.var_names["name"]].isel(
117
+ **{self.dim_names["station"]: i}
118
+ )
119
+ name = _decode_string(byte_array)
120
+ names.append(name)
121
+ ds[self.var_names["name"]] = xr.DataArray(
122
+ data=names, dims=self.dim_names["station"]
123
+ )
124
+
125
+ if ds[self.dim_names["station"]].dtype == "float64":
126
+ ds[self.dim_names["station"]] = ds[self.dim_names["station"]].astype(int)
127
+
128
+ # Drop all variables that have chars dim
129
+ vars_to_drop = ["ocn_name", "stn_name", "ct_name", "cn_name", "chars"]
130
+ existing_vars = [var for var in vars_to_drop if var in ds]
131
+ ds = ds.drop_vars(existing_vars)
132
+
133
+ return ds
134
+
135
+ def check_dataset(self, ds: xr.Dataset) -> None:
136
+ """Validate required variables, dimensions, and uniqueness of river names.
137
+
138
+ Parameters
139
+ ----------
140
+ ds : xr.Dataset
141
+ The xarray Dataset to check.
142
+
143
+ Raises
144
+ ------
145
+ ValueError
146
+ If the dataset does not contain the specified variables or dimensions.
147
+ """
148
+ check_dataset(ds, self.dim_names, self.var_names, self.opt_var_names)
149
+
150
+ def add_time_info(self, ds: xr.Dataset) -> xr.Dataset:
151
+ """Dummy method to be overridden by child classes to add time information to the
152
+ dataset.
153
+
154
+ This method is intended as a placeholder and should be implemented in subclasses
155
+ to provide specific functionality for adding time-related information to the dataset.
156
+
157
+ Parameters
158
+ ----------
159
+ ds : xr.Dataset
160
+ The xarray Dataset to which time information will be added.
161
+
162
+ Returns
163
+ -------
164
+ xr.Dataset
165
+ The xarray Dataset with time information added (as implemented by child classes).
166
+ """
167
+ return ds
168
+
169
+ def select_relevant_times(self, ds) -> xr.Dataset:
170
+ """Select a subset of the dataset based on the specified time range.
171
+
172
+ This method filters the dataset to include all records between `start_time` and `end_time`.
173
+ Additionally, it ensures that one record at or before `start_time` and one record at or
174
+ after `end_time` are included, even if they fall outside the strict time range.
175
+
176
+ If no `end_time` is specified, the method will select the time range of
177
+ [start_time, start_time + 24 hours] and return the closest time entry to `start_time` within that range.
178
+
179
+ Parameters
180
+ ----------
181
+ ds : xr.Dataset
182
+ The input dataset to be filtered. Must contain a time dimension.
183
+
184
+ Returns
185
+ -------
186
+ xr.Dataset
187
+ A dataset filtered to the specified time range, including the closest entries
188
+ at or before `start_time` and at or after `end_time` if applicable.
189
+
190
+ Warns
191
+ -----
192
+ UserWarning
193
+ If no records at or before `start_time` or no records at or after `end_time` are found.
194
+
195
+ UserWarning
196
+ If the dataset does not contain any time dimension or the time dimension is incorrectly named.
197
+ """
198
+ time_dim = self.dim_names["time"]
199
+
200
+ ds = select_relevant_times(
201
+ ds=ds,
202
+ time_dim=time_dim,
203
+ time_coord=time_dim,
204
+ start_time=self.start_time,
205
+ end_time=self.end_time,
206
+ )
207
+
208
+ return ds
209
+
210
+ def compute_climatology(self):
211
+ logging.info("Compute climatology for river forcing.")
212
+
213
+ time_dim = self.dim_names["time"]
214
+
215
+ flux = self.ds[self.var_names["flux"]].groupby(f"{time_dim}.month").mean()
216
+ self.ds[self.var_names["flux"]] = flux
217
+
218
+ ds = assign_dates_to_climatology(self.ds, "month")
219
+ ds = ds.swap_dims({"month": "time"})
220
+ self.ds = ds
221
+
222
+ updated_dim_names = {**self.dim_names}
223
+ updated_dim_names["time"] = "time"
224
+ self.dim_names = updated_dim_names
225
+
226
+ self.climatology = True
227
+
228
+ def sort_by_river_volume(self, ds: xr.Dataset) -> xr.Dataset:
229
+ """Sorts the dataset by river volume in descending order (largest rivers first),
230
+ if the volume variable is available.
231
+
232
+ This method uses the river volume to reorder the dataset such that the rivers with
233
+ the largest volumes come first in the `station` dimension. If the volume variable
234
+ is not present in the dataset, a warning is logged.
235
+
236
+ Parameters
237
+ ----------
238
+ ds : xr.Dataset
239
+ The xarray Dataset containing the river data to be sorted by volume.
240
+
241
+ Returns
242
+ -------
243
+ xr.Dataset
244
+ The dataset with rivers sorted by their volume in descending order.
245
+ If the volume variable is not available, the original dataset is returned.
246
+ """
247
+ if self.opt_var_names is not None and "vol" in self.opt_var_names:
248
+ volume_values = ds[self.opt_var_names["vol"]].values
249
+ if isinstance(volume_values, np.ndarray):
250
+ # Check if all volume values are the same
251
+ if np.all(volume_values == volume_values[0]):
252
+ # If all volumes are the same, no need to reverse order
253
+ sorted_indices = np.argsort(
254
+ volume_values
255
+ ) # Sort in ascending order
256
+ else:
257
+ # If volumes differ, reverse order for descending sort
258
+ sorted_indices = np.argsort(volume_values)[
259
+ ::-1
260
+ ] # Reverse for descending order
261
+
262
+ ds = ds.isel(**{self.dim_names["station"]: sorted_indices})
263
+
264
+ else:
265
+ logging.warning("The volume data is not in a valid array format.")
266
+ else:
267
+ logging.warning(
268
+ "Cannot sort rivers by volume. 'vol' is missing in the variable names."
269
+ )
270
+
271
+ return ds
272
+
273
+ def extract_relevant_rivers(self, target_coords, dx):
274
+ """Extracts a subset of the dataset based on the proximity of river mouths to
275
+ target coordinates.
276
+
277
+ This method calculates the distance between each river mouth and the provided target coordinates
278
+ (latitude and longitude) using the `gc_dist` function. It then filters the dataset to include only those
279
+ river stations whose minimum distance from the target is less than a specified threshold distance (`dx`).
280
+
281
+ Parameters
282
+ ----------
283
+ target_coords : dict
284
+ A dictionary containing the target coordinates for the comparison. It should include:
285
+ - "lon" (float): The target longitude in degrees.
286
+ - "lat" (float): The target latitude in degrees.
287
+ - "straddle" (bool): A flag indicating whether to adjust the longitudes for stations that cross the
288
+ International Date Line. If `True`, longitudes greater than 180 degrees are adjusted by subtracting 360,
289
+ otherwise, negative longitudes are adjusted by adding 360.
290
+
291
+ dx : float
292
+ The maximum distance threshold (in meters) for including a river station. Only river mouths that are
293
+ within `dx` meters from the target coordinates will be included in the returned dataset.
294
+
295
+ Returns
296
+ -------
297
+ indices : dict[str, list[tuple]]
298
+ A dictionary containing the indices of the rivers that are within the threshold distance from
299
+ the target coordinates. The dictionary structure consists of river names as keys, and each value is a list of tuples. Each tuple represents
300
+ a pair of indices corresponding to the `eta_rho` and `xi_rho` grid coordinates of the river.
301
+ """
302
+ # Retrieve longitude and latitude of river mouths
303
+ river_lon = self.ds[self.var_names["longitude"]]
304
+ river_lat = self.ds[self.var_names["latitude"]]
305
+
306
+ # Adjust longitude based on whether it crosses the International Date Line (straddle case)
307
+ if target_coords["straddle"]:
308
+ river_lon = xr.where(river_lon > 180, river_lon - 360, river_lon)
309
+ else:
310
+ river_lon = xr.where(river_lon < 0, river_lon + 360, river_lon)
311
+
312
+ # Calculate the distance between the target coordinates and each river mouth
313
+ dist = gc_dist(target_coords["lon"], target_coords["lat"], river_lon, river_lat)
314
+ dist_min = dist.min(dim=["eta_rho", "xi_rho"])
315
+ # Filter the dataset to include only stations within the distance threshold
316
+ if (dist_min < dx).any():
317
+ ds = self.ds.where(dist_min < dx, drop=True)
318
+ ds = self.sort_by_river_volume(ds)
319
+ dist = dist.where(dist_min < dx, drop=True).transpose(
320
+ self.dim_names["station"], "eta_rho", "xi_rho"
321
+ )
322
+
323
+ river_indices = get_indices_of_nearest_grid_cell_for_rivers(dist, self)
324
+ else:
325
+ ds = xr.Dataset()
326
+ river_indices = {}
327
+
328
+ self.ds = ds
329
+
330
+ return river_indices
331
+
332
+ def extract_named_rivers(self, indices):
333
+ """Extracts a subset of the dataset based on the provided river names in the
334
+ indices dictionary.
335
+
336
+ This method filters the dataset to include only the rivers specified in the `indices` dictionary.
337
+ The resulting subset is stored in the `ds` attribute of the class.
338
+
339
+ Parameters
340
+ ----------
341
+ indices : dict
342
+ A dictionary where the keys are river names (strings) and the values are dictionaries
343
+ containing river-related data (e.g., river indices, coordinates).
344
+
345
+ Returns
346
+ -------
347
+ None
348
+ The method modifies the `self.ds` attribute in place, setting it to the filtered dataset
349
+ containing only the data related to the specified rivers.
350
+
351
+ Raises
352
+ ------
353
+ ValueError
354
+ - If `indices` is not a dictionary.
355
+ - If any of the requested river names are not found in the dataset.
356
+ """
357
+ if not isinstance(indices, dict):
358
+ raise ValueError("`indices` must be a dictionary.")
359
+
360
+ river_names = list(indices.keys())
361
+
362
+ # Ensure the dataset is filtered based on the provided river names
363
+ ds_filtered = self.ds.where(
364
+ self.ds[self.var_names["name"]].isin(river_names), drop=True
365
+ )
366
+
367
+ # Check that all requested rivers exist in the dataset
368
+ filtered_river_names = set(ds_filtered[self.var_names["name"]].values)
369
+ missing_rivers = set(river_names) - filtered_river_names
370
+
371
+ if missing_rivers:
372
+ raise ValueError(
373
+ f"The following rivers were not found in the dataset: {missing_rivers}"
374
+ )
375
+
376
+ # Set the filtered dataset as the new `ds`
377
+ self.ds = ds_filtered
378
+
379
+
380
+ @dataclass(kw_only=True)
381
+ class DaiRiverDataset(RiverDataset):
382
+ """Represents river data from the Dai river dataset."""
383
+
384
+ filename: str | Path | list[str | Path] = field(
385
+ default_factory=lambda: download_river_data("dai_trenberth_may2019.nc")
386
+ )
387
+ dim_names: dict[str, str] = field(
388
+ default_factory=lambda: {
389
+ "station": "station",
390
+ "time": "time",
391
+ }
392
+ )
393
+ var_names: dict[str, str] = field(
394
+ default_factory=lambda: {
395
+ "latitude": "lat_mou",
396
+ "longitude": "lon_mou",
397
+ "flux": "FLOW",
398
+ "ratio": "ratio_m2s",
399
+ "name": "riv_name",
400
+ }
401
+ )
402
+ opt_var_names: dict[str, str] = field(
403
+ default_factory=lambda: {
404
+ "vol": "vol_stn",
405
+ }
406
+ )
407
+ climatology: bool = False
408
+
409
+ def add_time_info(self, ds: xr.Dataset) -> xr.Dataset:
410
+ """Adds time information to the dataset based on the climatology flag and
411
+ dimension names.
412
+
413
+ This method processes the dataset to include time information according to the climatology
414
+ setting. If the dataset represents climatology data and the time dimension is labeled as
415
+ "month", it assigns dates to the dataset based on a monthly climatology. Additionally, it
416
+ handles dimension name updates if necessary.
417
+
418
+ Parameters
419
+ ----------
420
+ ds : xr.Dataset
421
+ The input dataset to which time information will be added.
422
+
423
+ Returns
424
+ -------
425
+ xr.Dataset
426
+ The dataset with time information added, including adjustments for climatology and
427
+ dimension names.
428
+ """
429
+ time_dim = self.dim_names["time"]
430
+
431
+ # Extract the 'time' variable as a numpy array
432
+ time_vals = ds[time_dim].values
433
+
434
+ # Handle rounding of the time values
435
+ year = np.round(time_vals * 1e-2).astype(int)
436
+ month = np.round((time_vals * 1e-2 - year) * 1e2).astype(int)
437
+
438
+ # Convert to datetime (assuming the day is always 15th for this example)
439
+ dates = [datetime(year=i, month=m, day=15) for i, m in zip(year, month)]
440
+
441
+ ds[time_dim] = dates
442
+
443
+ return ds
444
+
445
+
446
+ def _decode_string(byte_array):
447
+ # Decode each byte and handle errors with 'ignore'
448
+ decoded_string = "".join(
449
+ [
450
+ x.decode("utf-8", errors="ignore") # Ignore invalid byte sequences
451
+ for x in byte_array.values
452
+ if isinstance(x, bytes) and x != b" " and x is not np.nan
453
+ ]
454
+ )
455
+
456
+ return decoded_string
457
+
458
+
459
+ def get_indices_of_nearest_grid_cell_for_rivers(
460
+ dist: xr.DataArray, data: RiverDataset
461
+ ) -> dict[str, list[tuple[int, int]]]:
462
+ """Get the indices of the nearest grid cell for each river based on distance.
463
+
464
+ Parameters
465
+ ----------
466
+ dist : xr.DataArray
467
+ A 2D or 3D array representing distances from each river to coastal grid cells,
468
+ with dimensions including "eta_rho" and "xi_rho".
469
+ data : RiverDataset
470
+ An instance of RiverDataset containing river names and dimension metadata.
471
+
472
+ Returns
473
+ -------
474
+ dict[str, list[tuple[int, int]]]
475
+ Dictionary mapping each river name to a list containing the (eta_rho, xi_rho) index
476
+ of the closest coastal grid cell.
477
+ """
478
+ # Find indices of the nearest coastal grid cell for each river
479
+ indices = dist.argmin(dim=["eta_rho", "xi_rho"])
480
+
481
+ eta_rho_values = indices["eta_rho"].values
482
+ xi_rho_values = indices["xi_rho"].values
483
+
484
+ # Get the corresponding station indices and river names
485
+ stations = indices["eta_rho"][data.dim_names["station"]].values
486
+ names = (
487
+ data.ds[data.var_names["name"]]
488
+ .sel({data.dim_names["station"]: stations})
489
+ .values
490
+ )
491
+
492
+ # Build dictionary of river name to grid index
493
+ river_indices = {
494
+ str(names[i]): [(int(eta_rho_values[i]), int(xi_rho_values[i]))]
495
+ for i in range(len(stations))
496
+ }
497
+
498
+ return river_indices
499
+
500
+
501
+ def _deduplicate_river_names(
502
+ ds: xr.Dataset, name_var: str, station_dim: str
503
+ ) -> xr.Dataset:
504
+ """Ensure river names are unique by appending _1, _2 to duplicates, excluding non-
505
+ duplicates.
506
+ """
507
+ original = ds[name_var]
508
+
509
+ # Force cast to plain Python strings
510
+ names = [str(name) for name in original.values]
511
+
512
+ # Count all names
513
+ name_counts = Counter(names)
514
+ seen: defaultdict[str, int] = defaultdict(int)
515
+
516
+ unique_names = []
517
+ for name in names:
518
+ if name_counts[name] > 1:
519
+ seen[name] += 1
520
+ unique_names.append(f"{name}_{seen[name]}")
521
+ else:
522
+ unique_names.append(name)
523
+
524
+ # Replace with updated names while preserving dtype, dims, attrs
525
+ updated_array = xr.DataArray(
526
+ data=np.array(unique_names, dtype=f"<U{max(len(n) for n in unique_names)}"),
527
+ dims=original.dims,
528
+ attrs=original.attrs,
529
+ )
530
+ ds[name_var] = updated_array
531
+
532
+ return ds