HydPy 6.2.dev1__cp313-cp313-win_amd64.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 (890) hide show
  1. hydpy/__init__.py +275 -0
  2. hydpy/aliases.py +2554 -0
  3. hydpy/auxs/__init__.py +0 -0
  4. hydpy/auxs/anntools.py +1305 -0
  5. hydpy/auxs/armatools.py +883 -0
  6. hydpy/auxs/calibtools.py +3337 -0
  7. hydpy/auxs/interptools.py +1094 -0
  8. hydpy/auxs/iuhtools.py +543 -0
  9. hydpy/auxs/networktools.py +597 -0
  10. hydpy/auxs/ppolytools.py +809 -0
  11. hydpy/auxs/quadtools.py +61 -0
  12. hydpy/auxs/roottools.py +228 -0
  13. hydpy/auxs/smoothtools.py +273 -0
  14. hydpy/auxs/statstools.py +2125 -0
  15. hydpy/auxs/validtools.py +81 -0
  16. hydpy/conf/HydPyConfigBase.xsd +68637 -0
  17. hydpy/conf/HydPyConfigBase.xsdt +358 -0
  18. hydpy/conf/HydPyConfigMultipleRuns.xsd +25 -0
  19. hydpy/conf/HydPyConfigSingleRun.xsd +24 -0
  20. hydpy/conf/__init__.py +0 -0
  21. hydpy/conf/a_coefficients_explicit_lobatto_sequence.npy +0 -0
  22. hydpy/conf/support_points_for_smoothpar_logistic2.npy +0 -0
  23. hydpy/config.py +42 -0
  24. hydpy/core/__init__.py +0 -0
  25. hydpy/core/aliastools.py +214 -0
  26. hydpy/core/autodoctools.py +1947 -0
  27. hydpy/core/auxfiletools.py +1169 -0
  28. hydpy/core/devicetools.py +3810 -0
  29. hydpy/core/exceptiontools.py +269 -0
  30. hydpy/core/filetools.py +1985 -0
  31. hydpy/core/hydpytools.py +3089 -0
  32. hydpy/core/importtools.py +1398 -0
  33. hydpy/core/indextools.py +345 -0
  34. hydpy/core/itemtools.py +1849 -0
  35. hydpy/core/masktools.py +460 -0
  36. hydpy/core/modeltools.py +4868 -0
  37. hydpy/core/netcdftools.py +2683 -0
  38. hydpy/core/objecttools.py +2023 -0
  39. hydpy/core/optiontools.py +1045 -0
  40. hydpy/core/parametertools.py +4674 -0
  41. hydpy/core/printtools.py +222 -0
  42. hydpy/core/propertytools.py +643 -0
  43. hydpy/core/pubtools.py +254 -0
  44. hydpy/core/selectiontools.py +1571 -0
  45. hydpy/core/sequencetools.py +4476 -0
  46. hydpy/core/seriestools.py +339 -0
  47. hydpy/core/testtools.py +2483 -0
  48. hydpy/core/timetools.py +3567 -0
  49. hydpy/core/typingtools.py +333 -0
  50. hydpy/core/variabletools.py +2615 -0
  51. hydpy/cythons/__init__.py +24 -0
  52. hydpy/cythons/annutils.pxd +33 -0
  53. hydpy/cythons/annutils.pyi +25 -0
  54. hydpy/cythons/annutils.pyx +120 -0
  55. hydpy/cythons/autogen/__init__.py +0 -0
  56. hydpy/cythons/autogen/annutils.cp313-win_amd64.pyd +0 -0
  57. hydpy/cythons/autogen/annutils.pxd +42 -0
  58. hydpy/cythons/autogen/annutils.pyx +129 -0
  59. hydpy/cythons/autogen/c_arma.cp313-win_amd64.pyd +0 -0
  60. hydpy/cythons/autogen/c_arma.pxd +179 -0
  61. hydpy/cythons/autogen/c_arma.pyx +356 -0
  62. hydpy/cythons/autogen/c_arma_rimorido.cp313-win_amd64.pyd +0 -0
  63. hydpy/cythons/autogen/c_arma_rimorido.pxd +179 -0
  64. hydpy/cythons/autogen/c_arma_rimorido.pyx +356 -0
  65. hydpy/cythons/autogen/c_conv.cp313-win_amd64.pyd +0 -0
  66. hydpy/cythons/autogen/c_conv.pxd +198 -0
  67. hydpy/cythons/autogen/c_conv.pyx +491 -0
  68. hydpy/cythons/autogen/c_conv_idw.cp313-win_amd64.pyd +0 -0
  69. hydpy/cythons/autogen/c_conv_idw.pxd +124 -0
  70. hydpy/cythons/autogen/c_conv_idw.pyx +264 -0
  71. hydpy/cythons/autogen/c_conv_idw_ed.cp313-win_amd64.pyd +0 -0
  72. hydpy/cythons/autogen/c_conv_idw_ed.pxd +197 -0
  73. hydpy/cythons/autogen/c_conv_idw_ed.pyx +481 -0
  74. hydpy/cythons/autogen/c_conv_nn.cp313-win_amd64.pyd +0 -0
  75. hydpy/cythons/autogen/c_conv_nn.pxd +120 -0
  76. hydpy/cythons/autogen/c_conv_nn.pyx +224 -0
  77. hydpy/cythons/autogen/c_dam.cp313-win_amd64.pyd +0 -0
  78. hydpy/cythons/autogen/c_dam.pxd +805 -0
  79. hydpy/cythons/autogen/c_dam.pyx +1477 -0
  80. hydpy/cythons/autogen/c_dam_llake.cp313-win_amd64.pyd +0 -0
  81. hydpy/cythons/autogen/c_dam_llake.pxd +364 -0
  82. hydpy/cythons/autogen/c_dam_llake.pyx +705 -0
  83. hydpy/cythons/autogen/c_dam_lreservoir.cp313-win_amd64.pyd +0 -0
  84. hydpy/cythons/autogen/c_dam_lreservoir.pxd +365 -0
  85. hydpy/cythons/autogen/c_dam_lreservoir.pyx +708 -0
  86. hydpy/cythons/autogen/c_dam_lretention.cp313-win_amd64.pyd +0 -0
  87. hydpy/cythons/autogen/c_dam_lretention.pxd +340 -0
  88. hydpy/cythons/autogen/c_dam_lretention.pyx +625 -0
  89. hydpy/cythons/autogen/c_dam_pump.cp313-win_amd64.pyd +0 -0
  90. hydpy/cythons/autogen/c_dam_pump.pxd +402 -0
  91. hydpy/cythons/autogen/c_dam_pump.pyx +724 -0
  92. hydpy/cythons/autogen/c_dam_pump_sluice.cp313-win_amd64.pyd +0 -0
  93. hydpy/cythons/autogen/c_dam_pump_sluice.pxd +452 -0
  94. hydpy/cythons/autogen/c_dam_pump_sluice.pyx +829 -0
  95. hydpy/cythons/autogen/c_dam_sluice.cp313-win_amd64.pyd +0 -0
  96. hydpy/cythons/autogen/c_dam_sluice.pxd +404 -0
  97. hydpy/cythons/autogen/c_dam_sluice.pyx +726 -0
  98. hydpy/cythons/autogen/c_dam_v001.cp313-win_amd64.pyd +0 -0
  99. hydpy/cythons/autogen/c_dam_v001.pxd +452 -0
  100. hydpy/cythons/autogen/c_dam_v001.pyx +816 -0
  101. hydpy/cythons/autogen/c_dam_v002.cp313-win_amd64.pyd +0 -0
  102. hydpy/cythons/autogen/c_dam_v002.pxd +394 -0
  103. hydpy/cythons/autogen/c_dam_v002.pyx +703 -0
  104. hydpy/cythons/autogen/c_dam_v003.cp313-win_amd64.pyd +0 -0
  105. hydpy/cythons/autogen/c_dam_v003.pxd +417 -0
  106. hydpy/cythons/autogen/c_dam_v003.pyx +744 -0
  107. hydpy/cythons/autogen/c_dam_v004.cp313-win_amd64.pyd +0 -0
  108. hydpy/cythons/autogen/c_dam_v004.pxd +486 -0
  109. hydpy/cythons/autogen/c_dam_v004.pyx +891 -0
  110. hydpy/cythons/autogen/c_dam_v005.cp313-win_amd64.pyd +0 -0
  111. hydpy/cythons/autogen/c_dam_v005.pxd +524 -0
  112. hydpy/cythons/autogen/c_dam_v005.pyx +928 -0
  113. hydpy/cythons/autogen/c_dummy.cp313-win_amd64.pyd +0 -0
  114. hydpy/cythons/autogen/c_dummy.pxd +151 -0
  115. hydpy/cythons/autogen/c_dummy.pyx +263 -0
  116. hydpy/cythons/autogen/c_dummy_interceptedwater.cp313-win_amd64.pyd +0 -0
  117. hydpy/cythons/autogen/c_dummy_interceptedwater.pxd +69 -0
  118. hydpy/cythons/autogen/c_dummy_interceptedwater.pyx +104 -0
  119. hydpy/cythons/autogen/c_dummy_node2node.cp313-win_amd64.pyd +0 -0
  120. hydpy/cythons/autogen/c_dummy_node2node.pxd +89 -0
  121. hydpy/cythons/autogen/c_dummy_node2node.pyx +148 -0
  122. hydpy/cythons/autogen/c_dummy_snowalbedo.cp313-win_amd64.pyd +0 -0
  123. hydpy/cythons/autogen/c_dummy_snowalbedo.pxd +69 -0
  124. hydpy/cythons/autogen/c_dummy_snowalbedo.pyx +104 -0
  125. hydpy/cythons/autogen/c_dummy_snowcover.cp313-win_amd64.pyd +0 -0
  126. hydpy/cythons/autogen/c_dummy_snowcover.pxd +69 -0
  127. hydpy/cythons/autogen/c_dummy_snowcover.pyx +104 -0
  128. hydpy/cythons/autogen/c_dummy_snowycanopy.cp313-win_amd64.pyd +0 -0
  129. hydpy/cythons/autogen/c_dummy_snowycanopy.pxd +69 -0
  130. hydpy/cythons/autogen/c_dummy_snowycanopy.pyx +104 -0
  131. hydpy/cythons/autogen/c_dummy_soilwater.cp313-win_amd64.pyd +0 -0
  132. hydpy/cythons/autogen/c_dummy_soilwater.pxd +69 -0
  133. hydpy/cythons/autogen/c_dummy_soilwater.pyx +104 -0
  134. hydpy/cythons/autogen/c_evap.cp313-win_amd64.pyd +0 -0
  135. hydpy/cythons/autogen/c_evap.pxd +1029 -0
  136. hydpy/cythons/autogen/c_evap.pyx +2601 -0
  137. hydpy/cythons/autogen/c_evap_aet_hbv96.cp313-win_amd64.pyd +0 -0
  138. hydpy/cythons/autogen/c_evap_aet_hbv96.pxd +227 -0
  139. hydpy/cythons/autogen/c_evap_aet_hbv96.pyx +584 -0
  140. hydpy/cythons/autogen/c_evap_aet_minhas.cp313-win_amd64.pyd +0 -0
  141. hydpy/cythons/autogen/c_evap_aet_minhas.pxd +193 -0
  142. hydpy/cythons/autogen/c_evap_aet_minhas.pyx +478 -0
  143. hydpy/cythons/autogen/c_evap_aet_morsim.cp313-win_amd64.pyd +0 -0
  144. hydpy/cythons/autogen/c_evap_aet_morsim.pxd +681 -0
  145. hydpy/cythons/autogen/c_evap_aet_morsim.pyx +1642 -0
  146. hydpy/cythons/autogen/c_evap_pet_ambav1.cp313-win_amd64.pyd +0 -0
  147. hydpy/cythons/autogen/c_evap_pet_ambav1.pxd +532 -0
  148. hydpy/cythons/autogen/c_evap_pet_ambav1.pyx +1296 -0
  149. hydpy/cythons/autogen/c_evap_pet_hbv96.cp313-win_amd64.pyd +0 -0
  150. hydpy/cythons/autogen/c_evap_pet_hbv96.pxd +179 -0
  151. hydpy/cythons/autogen/c_evap_pet_hbv96.pyx +328 -0
  152. hydpy/cythons/autogen/c_evap_pet_m.cp313-win_amd64.pyd +0 -0
  153. hydpy/cythons/autogen/c_evap_pet_m.pxd +124 -0
  154. hydpy/cythons/autogen/c_evap_pet_m.pyx +214 -0
  155. hydpy/cythons/autogen/c_evap_pet_mlc.cp313-win_amd64.pyd +0 -0
  156. hydpy/cythons/autogen/c_evap_pet_mlc.pxd +126 -0
  157. hydpy/cythons/autogen/c_evap_pet_mlc.pyx +214 -0
  158. hydpy/cythons/autogen/c_evap_ret_fao56.cp313-win_amd64.pyd +0 -0
  159. hydpy/cythons/autogen/c_evap_ret_fao56.pxd +305 -0
  160. hydpy/cythons/autogen/c_evap_ret_fao56.pyx +624 -0
  161. hydpy/cythons/autogen/c_evap_ret_io.cp313-win_amd64.pyd +0 -0
  162. hydpy/cythons/autogen/c_evap_ret_io.pxd +112 -0
  163. hydpy/cythons/autogen/c_evap_ret_io.pyx +176 -0
  164. hydpy/cythons/autogen/c_evap_ret_tw2002.cp313-win_amd64.pyd +0 -0
  165. hydpy/cythons/autogen/c_evap_ret_tw2002.pxd +139 -0
  166. hydpy/cythons/autogen/c_evap_ret_tw2002.pyx +273 -0
  167. hydpy/cythons/autogen/c_exch.cp313-win_amd64.pyd +0 -0
  168. hydpy/cythons/autogen/c_exch.pxd +230 -0
  169. hydpy/cythons/autogen/c_exch.pyx +462 -0
  170. hydpy/cythons/autogen/c_exch_branch_hbv96.cp313-win_amd64.pyd +0 -0
  171. hydpy/cythons/autogen/c_exch_branch_hbv96.pxd +134 -0
  172. hydpy/cythons/autogen/c_exch_branch_hbv96.pyx +255 -0
  173. hydpy/cythons/autogen/c_exch_waterlevel.cp313-win_amd64.pyd +0 -0
  174. hydpy/cythons/autogen/c_exch_waterlevel.pxd +54 -0
  175. hydpy/cythons/autogen/c_exch_waterlevel.pyx +78 -0
  176. hydpy/cythons/autogen/c_exch_weir_hbv96.cp313-win_amd64.pyd +0 -0
  177. hydpy/cythons/autogen/c_exch_weir_hbv96.pxd +156 -0
  178. hydpy/cythons/autogen/c_exch_weir_hbv96.pyx +282 -0
  179. hydpy/cythons/autogen/c_ga.cp313-win_amd64.pyd +0 -0
  180. hydpy/cythons/autogen/c_ga.pxd +353 -0
  181. hydpy/cythons/autogen/c_ga.pyx +1204 -0
  182. hydpy/cythons/autogen/c_ga_garto.cp313-win_amd64.pyd +0 -0
  183. hydpy/cythons/autogen/c_ga_garto.pxd +330 -0
  184. hydpy/cythons/autogen/c_ga_garto.pyx +1105 -0
  185. hydpy/cythons/autogen/c_ga_garto_submodel1.cp313-win_amd64.pyd +0 -0
  186. hydpy/cythons/autogen/c_ga_garto_submodel1.pxd +236 -0
  187. hydpy/cythons/autogen/c_ga_garto_submodel1.pyx +944 -0
  188. hydpy/cythons/autogen/c_gland.cp313-win_amd64.pyd +0 -0
  189. hydpy/cythons/autogen/c_gland.pxd +437 -0
  190. hydpy/cythons/autogen/c_gland.pyx +726 -0
  191. hydpy/cythons/autogen/c_gland_gr4.cp313-win_amd64.pyd +0 -0
  192. hydpy/cythons/autogen/c_gland_gr4.pxd +382 -0
  193. hydpy/cythons/autogen/c_gland_gr4.pyx +605 -0
  194. hydpy/cythons/autogen/c_gland_gr5.cp313-win_amd64.pyd +0 -0
  195. hydpy/cythons/autogen/c_gland_gr5.pxd +368 -0
  196. hydpy/cythons/autogen/c_gland_gr5.pyx +568 -0
  197. hydpy/cythons/autogen/c_gland_gr6.cp313-win_amd64.pyd +0 -0
  198. hydpy/cythons/autogen/c_gland_gr6.pxd +420 -0
  199. hydpy/cythons/autogen/c_gland_gr6.pyx +673 -0
  200. hydpy/cythons/autogen/c_hland.cp313-win_amd64.pyd +0 -0
  201. hydpy/cythons/autogen/c_hland.pxd +855 -0
  202. hydpy/cythons/autogen/c_hland.pyx +2486 -0
  203. hydpy/cythons/autogen/c_hland_96.cp313-win_amd64.pyd +0 -0
  204. hydpy/cythons/autogen/c_hland_96.pxd +631 -0
  205. hydpy/cythons/autogen/c_hland_96.pyx +1724 -0
  206. hydpy/cythons/autogen/c_hland_96c.cp313-win_amd64.pyd +0 -0
  207. hydpy/cythons/autogen/c_hland_96c.pxd +621 -0
  208. hydpy/cythons/autogen/c_hland_96c.pyx +1822 -0
  209. hydpy/cythons/autogen/c_hland_96p.cp313-win_amd64.pyd +0 -0
  210. hydpy/cythons/autogen/c_hland_96p.pxd +683 -0
  211. hydpy/cythons/autogen/c_hland_96p.pyx +1911 -0
  212. hydpy/cythons/autogen/c_kinw.cp313-win_amd64.pyd +0 -0
  213. hydpy/cythons/autogen/c_kinw.pxd +509 -0
  214. hydpy/cythons/autogen/c_kinw.pyx +965 -0
  215. hydpy/cythons/autogen/c_kinw_williams.cp313-win_amd64.pyd +0 -0
  216. hydpy/cythons/autogen/c_kinw_williams.pxd +409 -0
  217. hydpy/cythons/autogen/c_kinw_williams.pyx +763 -0
  218. hydpy/cythons/autogen/c_kinw_williams_ext.cp313-win_amd64.pyd +0 -0
  219. hydpy/cythons/autogen/c_kinw_williams_ext.pxd +220 -0
  220. hydpy/cythons/autogen/c_kinw_williams_ext.pyx +440 -0
  221. hydpy/cythons/autogen/c_lland.cp313-win_amd64.pyd +0 -0
  222. hydpy/cythons/autogen/c_lland.pxd +1386 -0
  223. hydpy/cythons/autogen/c_lland.pyx +3679 -0
  224. hydpy/cythons/autogen/c_lland_dd.cp313-win_amd64.pyd +0 -0
  225. hydpy/cythons/autogen/c_lland_dd.pxd +679 -0
  226. hydpy/cythons/autogen/c_lland_dd.pyx +1719 -0
  227. hydpy/cythons/autogen/c_lland_knauf.cp313-win_amd64.pyd +0 -0
  228. hydpy/cythons/autogen/c_lland_knauf.pxd +1096 -0
  229. hydpy/cythons/autogen/c_lland_knauf.pyx +2784 -0
  230. hydpy/cythons/autogen/c_lland_knauf_ic.cp313-win_amd64.pyd +0 -0
  231. hydpy/cythons/autogen/c_lland_knauf_ic.pxd +1369 -0
  232. hydpy/cythons/autogen/c_lland_knauf_ic.pyx +3625 -0
  233. hydpy/cythons/autogen/c_meteo.cp313-win_amd64.pyd +0 -0
  234. hydpy/cythons/autogen/c_meteo.pxd +469 -0
  235. hydpy/cythons/autogen/c_meteo.pyx +879 -0
  236. hydpy/cythons/autogen/c_meteo_clear_glob_io.cp313-win_amd64.pyd +0 -0
  237. hydpy/cythons/autogen/c_meteo_clear_glob_io.pxd +75 -0
  238. hydpy/cythons/autogen/c_meteo_clear_glob_io.pyx +107 -0
  239. hydpy/cythons/autogen/c_meteo_glob_fao56.cp313-win_amd64.pyd +0 -0
  240. hydpy/cythons/autogen/c_meteo_glob_fao56.pxd +209 -0
  241. hydpy/cythons/autogen/c_meteo_glob_fao56.pyx +339 -0
  242. hydpy/cythons/autogen/c_meteo_glob_io.cp313-win_amd64.pyd +0 -0
  243. hydpy/cythons/autogen/c_meteo_glob_io.pxd +63 -0
  244. hydpy/cythons/autogen/c_meteo_glob_io.pyx +91 -0
  245. hydpy/cythons/autogen/c_meteo_glob_morsim.cp313-win_amd64.pyd +0 -0
  246. hydpy/cythons/autogen/c_meteo_glob_morsim.pxd +289 -0
  247. hydpy/cythons/autogen/c_meteo_glob_morsim.pyx +527 -0
  248. hydpy/cythons/autogen/c_meteo_precip_io.cp313-win_amd64.pyd +0 -0
  249. hydpy/cythons/autogen/c_meteo_precip_io.pxd +112 -0
  250. hydpy/cythons/autogen/c_meteo_precip_io.pyx +176 -0
  251. hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.cp313-win_amd64.pyd +0 -0
  252. hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.pxd +87 -0
  253. hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.pyx +123 -0
  254. hydpy/cythons/autogen/c_meteo_sun_fao56.cp313-win_amd64.pyd +0 -0
  255. hydpy/cythons/autogen/c_meteo_sun_fao56.pxd +209 -0
  256. hydpy/cythons/autogen/c_meteo_sun_fao56.pyx +343 -0
  257. hydpy/cythons/autogen/c_meteo_sun_morsim.cp313-win_amd64.pyd +0 -0
  258. hydpy/cythons/autogen/c_meteo_sun_morsim.pxd +286 -0
  259. hydpy/cythons/autogen/c_meteo_sun_morsim.pyx +519 -0
  260. hydpy/cythons/autogen/c_meteo_temp_io.cp313-win_amd64.pyd +0 -0
  261. hydpy/cythons/autogen/c_meteo_temp_io.pxd +112 -0
  262. hydpy/cythons/autogen/c_meteo_temp_io.pyx +176 -0
  263. hydpy/cythons/autogen/c_musk.cp313-win_amd64.pyd +0 -0
  264. hydpy/cythons/autogen/c_musk.pxd +282 -0
  265. hydpy/cythons/autogen/c_musk.pyx +605 -0
  266. hydpy/cythons/autogen/c_musk_classic.cp313-win_amd64.pyd +0 -0
  267. hydpy/cythons/autogen/c_musk_classic.pxd +138 -0
  268. hydpy/cythons/autogen/c_musk_classic.pyx +226 -0
  269. hydpy/cythons/autogen/c_musk_mct.cp313-win_amd64.pyd +0 -0
  270. hydpy/cythons/autogen/c_musk_mct.pxd +282 -0
  271. hydpy/cythons/autogen/c_musk_mct.pyx +609 -0
  272. hydpy/cythons/autogen/c_rconc.cp313-win_amd64.pyd +0 -0
  273. hydpy/cythons/autogen/c_rconc.pxd +119 -0
  274. hydpy/cythons/autogen/c_rconc.pyx +174 -0
  275. hydpy/cythons/autogen/c_rconc_nash.cp313-win_amd64.pyd +0 -0
  276. hydpy/cythons/autogen/c_rconc_nash.pxd +111 -0
  277. hydpy/cythons/autogen/c_rconc_nash.pyx +185 -0
  278. hydpy/cythons/autogen/c_rconc_uh.cp313-win_amd64.pyd +0 -0
  279. hydpy/cythons/autogen/c_rconc_uh.pxd +92 -0
  280. hydpy/cythons/autogen/c_rconc_uh.pyx +125 -0
  281. hydpy/cythons/autogen/c_sw1d.cp313-win_amd64.pyd +0 -0
  282. hydpy/cythons/autogen/c_sw1d.pxd +511 -0
  283. hydpy/cythons/autogen/c_sw1d.pyx +1263 -0
  284. hydpy/cythons/autogen/c_sw1d_channel.cp313-win_amd64.pyd +0 -0
  285. hydpy/cythons/autogen/c_sw1d_channel.pxd +119 -0
  286. hydpy/cythons/autogen/c_sw1d_channel.pyx +300 -0
  287. hydpy/cythons/autogen/c_sw1d_gate_out.cp313-win_amd64.pyd +0 -0
  288. hydpy/cythons/autogen/c_sw1d_gate_out.pxd +240 -0
  289. hydpy/cythons/autogen/c_sw1d_gate_out.pyx +476 -0
  290. hydpy/cythons/autogen/c_sw1d_lias.cp313-win_amd64.pyd +0 -0
  291. hydpy/cythons/autogen/c_sw1d_lias.pxd +320 -0
  292. hydpy/cythons/autogen/c_sw1d_lias.pyx +619 -0
  293. hydpy/cythons/autogen/c_sw1d_lias_sluice.cp313-win_amd64.pyd +0 -0
  294. hydpy/cythons/autogen/c_sw1d_lias_sluice.pxd +325 -0
  295. hydpy/cythons/autogen/c_sw1d_lias_sluice.pyx +644 -0
  296. hydpy/cythons/autogen/c_sw1d_network.cp313-win_amd64.pyd +0 -0
  297. hydpy/cythons/autogen/c_sw1d_network.pxd +90 -0
  298. hydpy/cythons/autogen/c_sw1d_network.pyx +246 -0
  299. hydpy/cythons/autogen/c_sw1d_pump.cp313-win_amd64.pyd +0 -0
  300. hydpy/cythons/autogen/c_sw1d_pump.pxd +256 -0
  301. hydpy/cythons/autogen/c_sw1d_pump.pyx +502 -0
  302. hydpy/cythons/autogen/c_sw1d_q_in.cp313-win_amd64.pyd +0 -0
  303. hydpy/cythons/autogen/c_sw1d_q_in.pxd +224 -0
  304. hydpy/cythons/autogen/c_sw1d_q_in.pyx +383 -0
  305. hydpy/cythons/autogen/c_sw1d_q_out.cp313-win_amd64.pyd +0 -0
  306. hydpy/cythons/autogen/c_sw1d_q_out.pxd +224 -0
  307. hydpy/cythons/autogen/c_sw1d_q_out.pyx +383 -0
  308. hydpy/cythons/autogen/c_sw1d_storage.cp313-win_amd64.pyd +0 -0
  309. hydpy/cythons/autogen/c_sw1d_storage.pxd +193 -0
  310. hydpy/cythons/autogen/c_sw1d_storage.pyx +349 -0
  311. hydpy/cythons/autogen/c_sw1d_weir_out.cp313-win_amd64.pyd +0 -0
  312. hydpy/cythons/autogen/c_sw1d_weir_out.pxd +212 -0
  313. hydpy/cythons/autogen/c_sw1d_weir_out.pyx +404 -0
  314. hydpy/cythons/autogen/c_test.cp313-win_amd64.pyd +0 -0
  315. hydpy/cythons/autogen/c_test.pxd +175 -0
  316. hydpy/cythons/autogen/c_test.pyx +348 -0
  317. hydpy/cythons/autogen/c_test_discontinous.cp313-win_amd64.pyd +0 -0
  318. hydpy/cythons/autogen/c_test_discontinous.pxd +146 -0
  319. hydpy/cythons/autogen/c_test_discontinous.pyx +256 -0
  320. hydpy/cythons/autogen/c_test_stiff0d.cp313-win_amd64.pyd +0 -0
  321. hydpy/cythons/autogen/c_test_stiff0d.pxd +146 -0
  322. hydpy/cythons/autogen/c_test_stiff0d.pyx +250 -0
  323. hydpy/cythons/autogen/c_test_stiff1d.cp313-win_amd64.pyd +0 -0
  324. hydpy/cythons/autogen/c_test_stiff1d.pxd +145 -0
  325. hydpy/cythons/autogen/c_test_stiff1d.pyx +294 -0
  326. hydpy/cythons/autogen/c_whmod.cp313-win_amd64.pyd +0 -0
  327. hydpy/cythons/autogen/c_whmod.pxd +482 -0
  328. hydpy/cythons/autogen/c_whmod.pyx +1156 -0
  329. hydpy/cythons/autogen/c_whmod_rural.cp313-win_amd64.pyd +0 -0
  330. hydpy/cythons/autogen/c_whmod_rural.pxd +411 -0
  331. hydpy/cythons/autogen/c_whmod_rural.pyx +982 -0
  332. hydpy/cythons/autogen/c_whmod_urban.cp313-win_amd64.pyd +0 -0
  333. hydpy/cythons/autogen/c_whmod_urban.pxd +482 -0
  334. hydpy/cythons/autogen/c_whmod_urban.pyx +1155 -0
  335. hydpy/cythons/autogen/c_wland.cp313-win_amd64.pyd +0 -0
  336. hydpy/cythons/autogen/c_wland.pxd +842 -0
  337. hydpy/cythons/autogen/c_wland.pyx +1890 -0
  338. hydpy/cythons/autogen/c_wland_gd.cp313-win_amd64.pyd +0 -0
  339. hydpy/cythons/autogen/c_wland_gd.pxd +829 -0
  340. hydpy/cythons/autogen/c_wland_gd.pyx +1847 -0
  341. hydpy/cythons/autogen/c_wland_wag.cp313-win_amd64.pyd +0 -0
  342. hydpy/cythons/autogen/c_wland_wag.pxd +810 -0
  343. hydpy/cythons/autogen/c_wland_wag.pyx +1780 -0
  344. hydpy/cythons/autogen/c_wq.cp313-win_amd64.pyd +0 -0
  345. hydpy/cythons/autogen/c_wq.pxd +275 -0
  346. hydpy/cythons/autogen/c_wq.pyx +652 -0
  347. hydpy/cythons/autogen/c_wq_trapeze.cp313-win_amd64.pyd +0 -0
  348. hydpy/cythons/autogen/c_wq_trapeze.pxd +170 -0
  349. hydpy/cythons/autogen/c_wq_trapeze.pyx +400 -0
  350. hydpy/cythons/autogen/c_wq_trapeze_strickler.cp313-win_amd64.pyd +0 -0
  351. hydpy/cythons/autogen/c_wq_trapeze_strickler.pxd +243 -0
  352. hydpy/cythons/autogen/c_wq_trapeze_strickler.pyx +578 -0
  353. hydpy/cythons/autogen/c_wq_walrus.cp313-win_amd64.pyd +0 -0
  354. hydpy/cythons/autogen/c_wq_walrus.pxd +61 -0
  355. hydpy/cythons/autogen/c_wq_walrus.pyx +82 -0
  356. hydpy/cythons/autogen/configutils.cp313-win_amd64.pyd +0 -0
  357. hydpy/cythons/autogen/configutils.pxd +17 -0
  358. hydpy/cythons/autogen/configutils.pyx +119 -0
  359. hydpy/cythons/autogen/interfaceutils.cp313-win_amd64.pyd +0 -0
  360. hydpy/cythons/autogen/interfaceutils.pxd +31 -0
  361. hydpy/cythons/autogen/interfaceutils.pyx +82 -0
  362. hydpy/cythons/autogen/interputils.cp313-win_amd64.pyd +0 -0
  363. hydpy/cythons/autogen/interputils.pxd +42 -0
  364. hydpy/cythons/autogen/interputils.pyx +118 -0
  365. hydpy/cythons/autogen/masterinterface.cp313-win_amd64.pyd +0 -0
  366. hydpy/cythons/autogen/masterinterface.pxd +153 -0
  367. hydpy/cythons/autogen/masterinterface.pyx +222 -0
  368. hydpy/cythons/autogen/pointerutils.cp313-win_amd64.pyd +0 -0
  369. hydpy/cythons/autogen/pointerutils.pxd +31 -0
  370. hydpy/cythons/autogen/pointerutils.pyx +650 -0
  371. hydpy/cythons/autogen/ppolyutils.cp313-win_amd64.pyd +0 -0
  372. hydpy/cythons/autogen/ppolyutils.pxd +35 -0
  373. hydpy/cythons/autogen/ppolyutils.pyx +59 -0
  374. hydpy/cythons/autogen/quadutils.cp313-win_amd64.pyd +0 -0
  375. hydpy/cythons/autogen/quadutils.pxd +26 -0
  376. hydpy/cythons/autogen/quadutils.pyx +973 -0
  377. hydpy/cythons/autogen/rootutils.cp313-win_amd64.pyd +0 -0
  378. hydpy/cythons/autogen/rootutils.pxd +28 -0
  379. hydpy/cythons/autogen/rootutils.pyx +109 -0
  380. hydpy/cythons/autogen/sequenceutils.cp313-win_amd64.pyd +0 -0
  381. hydpy/cythons/autogen/sequenceutils.pxd +45 -0
  382. hydpy/cythons/autogen/sequenceutils.pyx +101 -0
  383. hydpy/cythons/autogen/smoothutils.cp313-win_amd64.pyd +0 -0
  384. hydpy/cythons/autogen/smoothutils.pxd +29 -0
  385. hydpy/cythons/autogen/smoothutils.pyx +833 -0
  386. hydpy/cythons/configutils.pxd +8 -0
  387. hydpy/cythons/configutils.pyi +5 -0
  388. hydpy/cythons/configutils.pyx +110 -0
  389. hydpy/cythons/interfaceutils.pxd +22 -0
  390. hydpy/cythons/interfaceutils.pyi +15 -0
  391. hydpy/cythons/interfaceutils.pyx +73 -0
  392. hydpy/cythons/interputils.pxd +33 -0
  393. hydpy/cythons/interputils.pyi +32 -0
  394. hydpy/cythons/interputils.pyx +109 -0
  395. hydpy/cythons/modelutils.py +2990 -0
  396. hydpy/cythons/pointerutils.pxd +22 -0
  397. hydpy/cythons/pointerutils.pyi +89 -0
  398. hydpy/cythons/pointerutils.pyx +641 -0
  399. hydpy/cythons/ppolyutils.pxd +26 -0
  400. hydpy/cythons/ppolyutils.pyi +21 -0
  401. hydpy/cythons/ppolyutils.pyx +50 -0
  402. hydpy/cythons/quadutils.pxd +17 -0
  403. hydpy/cythons/quadutils.pyi +13 -0
  404. hydpy/cythons/quadutils.pyx +964 -0
  405. hydpy/cythons/rootutils.pxd +19 -0
  406. hydpy/cythons/rootutils.pyi +21 -0
  407. hydpy/cythons/rootutils.pyx +100 -0
  408. hydpy/cythons/sequenceutils.pxd +36 -0
  409. hydpy/cythons/sequenceutils.pyi +7 -0
  410. hydpy/cythons/sequenceutils.pyx +92 -0
  411. hydpy/cythons/smoothutils.pxd +20 -0
  412. hydpy/cythons/smoothutils.pyi +15 -0
  413. hydpy/cythons/smoothutils.pyx +824 -0
  414. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_dill_assl.py +13 -0
  415. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_kalk.py +13 -0
  416. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_leun.py +14 -0
  417. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_marb.py +13 -0
  418. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_dill_assl_lahn_leun.py +5 -0
  419. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_lahn_leun_lahn_kalk.py +5 -0
  420. hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_lahn_marb_lahn_leun.py +5 -0
  421. hydpy/data/HydPy-H-Lahn/control/default/land.py +9 -0
  422. hydpy/data/HydPy-H-Lahn/control/default/land_dill_assl.py +57 -0
  423. hydpy/data/HydPy-H-Lahn/control/default/land_lahn_kalk.py +57 -0
  424. hydpy/data/HydPy-H-Lahn/control/default/land_lahn_leun.py +56 -0
  425. hydpy/data/HydPy-H-Lahn/control/default/land_lahn_marb.py +57 -0
  426. hydpy/data/HydPy-H-Lahn/control/default/stream_dill_assl_lahn_leun.py +7 -0
  427. hydpy/data/HydPy-H-Lahn/control/default/stream_lahn_leun_lahn_kalk.py +7 -0
  428. hydpy/data/HydPy-H-Lahn/control/default/stream_lahn_marb_lahn_leun.py +7 -0
  429. hydpy/data/HydPy-H-Lahn/multiple_runs.xml +309 -0
  430. hydpy/data/HydPy-H-Lahn/multiple_runs_alpha.xml +71 -0
  431. hydpy/data/HydPy-H-Lahn/network/default/headwaters.py +11 -0
  432. hydpy/data/HydPy-H-Lahn/network/default/nonheadwaters.py +11 -0
  433. hydpy/data/HydPy-H-Lahn/network/default/streams.py +8 -0
  434. hydpy/data/HydPy-H-Lahn/series/default/dill_assl_obs_q.asc +11387 -0
  435. hydpy/data/HydPy-H-Lahn/series/default/evap_pet_hbv96_input_normalairtemperature.nc +0 -0
  436. hydpy/data/HydPy-H-Lahn/series/default/evap_pet_hbv96_input_normalevapotranspiration.nc +0 -0
  437. hydpy/data/HydPy-H-Lahn/series/default/hland_96_input_p.nc +0 -0
  438. hydpy/data/HydPy-H-Lahn/series/default/hland_96_input_t.nc +0 -0
  439. hydpy/data/HydPy-H-Lahn/series/default/lahn_kalk_obs_q.asc +11387 -0
  440. hydpy/data/HydPy-H-Lahn/series/default/lahn_leun_obs_q.asc +11387 -0
  441. hydpy/data/HydPy-H-Lahn/series/default/lahn_marb_obs_q.asc +11387 -0
  442. hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
  443. hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
  444. hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_hland_96_input_p.asc +11387 -0
  445. hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_hland_96_input_t.asc +11387 -0
  446. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
  447. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
  448. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_hland_96_input_p.asc +11387 -0
  449. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_hland_96_input_t.asc +11387 -0
  450. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
  451. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
  452. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_hland_96_input_p.asc +11387 -0
  453. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_hland_96_input_t.asc +11387 -0
  454. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
  455. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
  456. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_hland_96_input_p.asc +11387 -0
  457. hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_hland_96_input_t.asc +11387 -0
  458. hydpy/data/HydPy-H-Lahn/series/default/obs_q.nc +0 -0
  459. hydpy/data/HydPy-H-Lahn/single_run.xml +152 -0
  460. hydpy/data/HydPy-H-Lahn/single_run.xmlt +143 -0
  461. hydpy/data/__init__.py +17 -0
  462. hydpy/docs/__init__.py +0 -0
  463. hydpy/docs/autofigs/__init__.py +0 -0
  464. hydpy/docs/bib/__init__.py +0 -0
  465. hydpy/docs/bib/refs.bib +566 -0
  466. hydpy/docs/combine_docversions.py +133 -0
  467. hydpy/docs/draw_model_sketches.py +1301 -0
  468. hydpy/docs/enable_autodoc.py +7 -0
  469. hydpy/docs/figs/HydPy-G-GR4.png +0 -0
  470. hydpy/docs/figs/HydPy-G-GR5.png +0 -0
  471. hydpy/docs/figs/HydPy-G-GR6.png +0 -0
  472. hydpy/docs/figs/HydPy-H-HBV96-COSERO.png +0 -0
  473. hydpy/docs/figs/HydPy-H-HBV96-PREVAH.png +0 -0
  474. hydpy/docs/figs/HydPy-H-HBV96.png +0 -0
  475. hydpy/docs/figs/HydPy-H-Lahn.png +0 -0
  476. hydpy/docs/figs/HydPy-KinW-Williams.png +0 -0
  477. hydpy/docs/figs/HydPy-L-DD.png +0 -0
  478. hydpy/docs/figs/HydPy-W-Wag.png +0 -0
  479. hydpy/docs/figs/HydPy_Logo.png +0 -0
  480. hydpy/docs/figs/HydPy_Logo_Text.png +0 -0
  481. hydpy/docs/figs/IDLE-editor.png +0 -0
  482. hydpy/docs/figs/IDLE-shell.png +0 -0
  483. hydpy/docs/figs/LAWA_river-basin-bumbers.png +0 -0
  484. hydpy/docs/figs/__init__.py +0 -0
  485. hydpy/docs/html_/__init__.py +0 -0
  486. hydpy/docs/polish_html.py +57 -0
  487. hydpy/docs/prepare.py +224 -0
  488. hydpy/docs/publish_docs.py +53 -0
  489. hydpy/docs/rst/HydPy-ARMA.rst +27 -0
  490. hydpy/docs/rst/HydPy-Conv.rst +22 -0
  491. hydpy/docs/rst/HydPy-Dam.rst +79 -0
  492. hydpy/docs/rst/HydPy-Dummy.rst +21 -0
  493. hydpy/docs/rst/HydPy-Evap.rst +26 -0
  494. hydpy/docs/rst/HydPy-Exch.rst +36 -0
  495. hydpy/docs/rst/HydPy-G.rst +40 -0
  496. hydpy/docs/rst/HydPy-GA.rst +34 -0
  497. hydpy/docs/rst/HydPy-H.rst +24 -0
  498. hydpy/docs/rst/HydPy-KinW.rst +32 -0
  499. hydpy/docs/rst/HydPy-L.rst +42 -0
  500. hydpy/docs/rst/HydPy-Meteo.rst +28 -0
  501. hydpy/docs/rst/HydPy-Musk.rst +21 -0
  502. hydpy/docs/rst/HydPy-Rconc.rst +17 -0
  503. hydpy/docs/rst/HydPy-SW1D.rst +49 -0
  504. hydpy/docs/rst/HydPy-Test.rst +19 -0
  505. hydpy/docs/rst/HydPy-W.rst +20 -0
  506. hydpy/docs/rst/HydPy-WHMod.rst +19 -0
  507. hydpy/docs/rst/HydPy-WQ.rst +20 -0
  508. hydpy/docs/rst/__init__.py +0 -0
  509. hydpy/docs/rst/additional_repositories.rst +40 -0
  510. hydpy/docs/rst/auxiliaries.rst +31 -0
  511. hydpy/docs/rst/continuous_integration.rst +75 -0
  512. hydpy/docs/rst/core.rst +75 -0
  513. hydpy/docs/rst/cythons.rst +47 -0
  514. hydpy/docs/rst/definitions.rst +506 -0
  515. hydpy/docs/rst/developer_guide.rst +54 -0
  516. hydpy/docs/rst/example_projects.rst +40 -0
  517. hydpy/docs/rst/execution.rst +22 -0
  518. hydpy/docs/rst/framework_tools.rst +56 -0
  519. hydpy/docs/rst/how_to_read_the_reference_manual.rst +156 -0
  520. hydpy/docs/rst/hydpydependencies.rst +55 -0
  521. hydpy/docs/rst/index.rst +125 -0
  522. hydpy/docs/rst/installation.rst +155 -0
  523. hydpy/docs/rst/model_families.rst +79 -0
  524. hydpy/docs/rst/model_overview.rst +291 -0
  525. hydpy/docs/rst/modelimports.rst +10 -0
  526. hydpy/docs/rst/options.rst +119 -0
  527. hydpy/docs/rst/programming_style.rst +572 -0
  528. hydpy/docs/rst/project_structure.rst +520 -0
  529. hydpy/docs/rst/quickstart.rst +304 -0
  530. hydpy/docs/rst/reference_manual.rst +29 -0
  531. hydpy/docs/rst/required_tools.rst +50 -0
  532. hydpy/docs/rst/simulation.rst +514 -0
  533. hydpy/docs/rst/submodel_interfaces.rst +32 -0
  534. hydpy/docs/rst/tests_and_documentation.rst +85 -0
  535. hydpy/docs/rst/user_guide.rst +38 -0
  536. hydpy/docs/rst/version_control.rst +116 -0
  537. hydpy/docs/rst/zbibliography.rst +8 -0
  538. hydpy/docs/sphinx/__init__.py +0 -0
  539. hydpy/docs/sphinx/_themes/basic_hydpy/changes/frameset.html +11 -0
  540. hydpy/docs/sphinx/_themes/basic_hydpy/changes/rstsource.html +15 -0
  541. hydpy/docs/sphinx/_themes/basic_hydpy/changes/versionchanges.html +33 -0
  542. hydpy/docs/sphinx/_themes/basic_hydpy/defindex.html +35 -0
  543. hydpy/docs/sphinx/_themes/basic_hydpy/domainindex.html +56 -0
  544. hydpy/docs/sphinx/_themes/basic_hydpy/genindex-single.html +63 -0
  545. hydpy/docs/sphinx/_themes/basic_hydpy/genindex-split.html +41 -0
  546. hydpy/docs/sphinx/_themes/basic_hydpy/genindex.html +76 -0
  547. hydpy/docs/sphinx/_themes/basic_hydpy/globaltoc.html +11 -0
  548. hydpy/docs/sphinx/_themes/basic_hydpy/layout.html +221 -0
  549. hydpy/docs/sphinx/_themes/basic_hydpy/localtoc.html +15 -0
  550. hydpy/docs/sphinx/_themes/basic_hydpy/opensearch.xml +13 -0
  551. hydpy/docs/sphinx/_themes/basic_hydpy/page.html +13 -0
  552. hydpy/docs/sphinx/_themes/basic_hydpy/relations.html +23 -0
  553. hydpy/docs/sphinx/_themes/basic_hydpy/search.html +65 -0
  554. hydpy/docs/sphinx/_themes/basic_hydpy/searchbox.html +21 -0
  555. hydpy/docs/sphinx/_themes/basic_hydpy/searchfield.html +23 -0
  556. hydpy/docs/sphinx/_themes/basic_hydpy/sourcelink.html +18 -0
  557. hydpy/docs/sphinx/_themes/basic_hydpy/static/basic.css_t +925 -0
  558. hydpy/docs/sphinx/_themes/basic_hydpy/static/doctools.js +156 -0
  559. hydpy/docs/sphinx/_themes/basic_hydpy/static/documentation_options.js_t +13 -0
  560. hydpy/docs/sphinx/_themes/basic_hydpy/static/file.png +0 -0
  561. hydpy/docs/sphinx/_themes/basic_hydpy/static/language_data.js_t +26 -0
  562. hydpy/docs/sphinx/_themes/basic_hydpy/static/minus.png +0 -0
  563. hydpy/docs/sphinx/_themes/basic_hydpy/static/plus.png +0 -0
  564. hydpy/docs/sphinx/_themes/basic_hydpy/static/searchtools.js +574 -0
  565. hydpy/docs/sphinx/_themes/basic_hydpy/static/sphinx_highlight.js +154 -0
  566. hydpy/docs/sphinx/_themes/basic_hydpy/theme.conf +16 -0
  567. hydpy/docs/sphinx/_themes/classic_hydpy/layout.html +23 -0
  568. hydpy/docs/sphinx/_themes/classic_hydpy/static/classic.css_t +358 -0
  569. hydpy/docs/sphinx/_themes/classic_hydpy/static/sidebar.js_t +72 -0
  570. hydpy/docs/sphinx/_themes/classic_hydpy/theme.conf +32 -0
  571. hydpy/docs/sphinx/conf.py +398 -0
  572. hydpy/docs/sphinx/defaultlinks_extension.py +36 -0
  573. hydpy/docs/sphinx/integrationtest_extension.py +104 -0
  574. hydpy/docs/sphinx/projectstructure_extension.py +58 -0
  575. hydpy/docs/sphinx/submodelgraph_extension.py +53 -0
  576. hydpy/exe/__init__.py +0 -0
  577. hydpy/exe/commandtools.py +651 -0
  578. hydpy/exe/hyd.py +277 -0
  579. hydpy/exe/modelimports.py +41 -0
  580. hydpy/exe/replacetools.py +216 -0
  581. hydpy/exe/servertools.py +2348 -0
  582. hydpy/exe/xmltools.py +3280 -0
  583. hydpy/interfaces/__init__.py +0 -0
  584. hydpy/interfaces/aetinterfaces.py +94 -0
  585. hydpy/interfaces/dischargeinterfaces.py +45 -0
  586. hydpy/interfaces/petinterfaces.py +117 -0
  587. hydpy/interfaces/precipinterfaces.py +42 -0
  588. hydpy/interfaces/radiationinterfaces.py +79 -0
  589. hydpy/interfaces/rconcinterfaces.py +30 -0
  590. hydpy/interfaces/routinginterfaces.py +324 -0
  591. hydpy/interfaces/soilinterfaces.py +96 -0
  592. hydpy/interfaces/stateinterfaces.py +98 -0
  593. hydpy/interfaces/tempinterfaces.py +46 -0
  594. hydpy/models/__init__.py +0 -0
  595. hydpy/models/arma/__init__.py +14 -0
  596. hydpy/models/arma/arma_control.py +383 -0
  597. hydpy/models/arma/arma_derived.py +204 -0
  598. hydpy/models/arma/arma_fluxes.py +41 -0
  599. hydpy/models/arma/arma_inlets.py +11 -0
  600. hydpy/models/arma/arma_logs.py +19 -0
  601. hydpy/models/arma/arma_model.py +461 -0
  602. hydpy/models/arma/arma_outlets.py +11 -0
  603. hydpy/models/arma_rimorido.py +381 -0
  604. hydpy/models/conv/__init__.py +12 -0
  605. hydpy/models/conv/conv_control.py +303 -0
  606. hydpy/models/conv/conv_derived.py +271 -0
  607. hydpy/models/conv/conv_fluxes.py +54 -0
  608. hydpy/models/conv/conv_inlets.py +11 -0
  609. hydpy/models/conv/conv_model.py +687 -0
  610. hydpy/models/conv/conv_outlets.py +11 -0
  611. hydpy/models/conv_idw.py +120 -0
  612. hydpy/models/conv_idw_ed.py +184 -0
  613. hydpy/models/conv_nn.py +112 -0
  614. hydpy/models/dam/__init__.py +16 -0
  615. hydpy/models/dam/dam_aides.py +17 -0
  616. hydpy/models/dam/dam_control.py +346 -0
  617. hydpy/models/dam/dam_derived.py +559 -0
  618. hydpy/models/dam/dam_factors.py +46 -0
  619. hydpy/models/dam/dam_fluxes.py +179 -0
  620. hydpy/models/dam/dam_inlets.py +29 -0
  621. hydpy/models/dam/dam_logs.py +52 -0
  622. hydpy/models/dam/dam_model.py +5011 -0
  623. hydpy/models/dam/dam_outlets.py +23 -0
  624. hydpy/models/dam/dam_receivers.py +41 -0
  625. hydpy/models/dam/dam_senders.py +23 -0
  626. hydpy/models/dam/dam_solver.py +75 -0
  627. hydpy/models/dam/dam_states.py +11 -0
  628. hydpy/models/dam_llake.py +499 -0
  629. hydpy/models/dam_lreservoir.py +548 -0
  630. hydpy/models/dam_lretention.py +343 -0
  631. hydpy/models/dam_pump.py +278 -0
  632. hydpy/models/dam_pump_sluice.py +339 -0
  633. hydpy/models/dam_sluice.py +319 -0
  634. hydpy/models/dam_v001.py +1127 -0
  635. hydpy/models/dam_v002.py +381 -0
  636. hydpy/models/dam_v003.py +422 -0
  637. hydpy/models/dam_v004.py +665 -0
  638. hydpy/models/dam_v005.py +479 -0
  639. hydpy/models/dummy/__init__.py +15 -0
  640. hydpy/models/dummy/dummy_control.py +22 -0
  641. hydpy/models/dummy/dummy_fluxes.py +11 -0
  642. hydpy/models/dummy/dummy_inlets.py +11 -0
  643. hydpy/models/dummy/dummy_inputs.py +41 -0
  644. hydpy/models/dummy/dummy_model.py +196 -0
  645. hydpy/models/dummy/dummy_outlets.py +11 -0
  646. hydpy/models/dummy_interceptedwater.py +85 -0
  647. hydpy/models/dummy_node2node.py +83 -0
  648. hydpy/models/dummy_snowalbedo.py +84 -0
  649. hydpy/models/dummy_snowcover.py +84 -0
  650. hydpy/models/dummy_snowycanopy.py +86 -0
  651. hydpy/models/dummy_soilwater.py +85 -0
  652. hydpy/models/evap/__init__.py +13 -0
  653. hydpy/models/evap/evap_control.py +354 -0
  654. hydpy/models/evap/evap_derived.py +236 -0
  655. hydpy/models/evap/evap_factors.py +188 -0
  656. hydpy/models/evap/evap_fixed.py +68 -0
  657. hydpy/models/evap/evap_fluxes.py +150 -0
  658. hydpy/models/evap/evap_inputs.py +54 -0
  659. hydpy/models/evap/evap_logs.py +91 -0
  660. hydpy/models/evap/evap_masks.py +48 -0
  661. hydpy/models/evap/evap_model.py +9170 -0
  662. hydpy/models/evap/evap_parameters.py +149 -0
  663. hydpy/models/evap/evap_sequences.py +32 -0
  664. hydpy/models/evap/evap_states.py +18 -0
  665. hydpy/models/evap_aet_hbv96.py +372 -0
  666. hydpy/models/evap_aet_minhas.py +331 -0
  667. hydpy/models/evap_aet_morsim.py +627 -0
  668. hydpy/models/evap_pet_ambav1.py +483 -0
  669. hydpy/models/evap_pet_hbv96.py +147 -0
  670. hydpy/models/evap_pet_m.py +94 -0
  671. hydpy/models/evap_pet_mlc.py +107 -0
  672. hydpy/models/evap_ret_fao56.py +265 -0
  673. hydpy/models/evap_ret_io.py +74 -0
  674. hydpy/models/evap_ret_tw2002.py +165 -0
  675. hydpy/models/exch/__init__.py +14 -0
  676. hydpy/models/exch/exch_control.py +262 -0
  677. hydpy/models/exch/exch_derived.py +36 -0
  678. hydpy/models/exch/exch_factors.py +26 -0
  679. hydpy/models/exch/exch_fluxes.py +48 -0
  680. hydpy/models/exch/exch_inlets.py +11 -0
  681. hydpy/models/exch/exch_logs.py +12 -0
  682. hydpy/models/exch/exch_model.py +451 -0
  683. hydpy/models/exch/exch_outlets.py +17 -0
  684. hydpy/models/exch/exch_receivers.py +17 -0
  685. hydpy/models/exch_branch_hbv96.py +186 -0
  686. hydpy/models/exch_waterlevel.py +73 -0
  687. hydpy/models/exch_weir_hbv96.py +609 -0
  688. hydpy/models/ga/__init__.py +14 -0
  689. hydpy/models/ga/ga_aides.py +17 -0
  690. hydpy/models/ga/ga_control.py +208 -0
  691. hydpy/models/ga/ga_derived.py +77 -0
  692. hydpy/models/ga/ga_fluxes.py +83 -0
  693. hydpy/models/ga/ga_inputs.py +26 -0
  694. hydpy/models/ga/ga_logs.py +17 -0
  695. hydpy/models/ga/ga_model.py +2952 -0
  696. hydpy/models/ga/ga_states.py +87 -0
  697. hydpy/models/ga_garto.py +1001 -0
  698. hydpy/models/ga_garto_submodel1.py +79 -0
  699. hydpy/models/gland/__init__.py +14 -0
  700. hydpy/models/gland/gland_control.py +90 -0
  701. hydpy/models/gland/gland_derived.py +113 -0
  702. hydpy/models/gland/gland_fluxes.py +137 -0
  703. hydpy/models/gland/gland_inputs.py +12 -0
  704. hydpy/models/gland/gland_model.py +1439 -0
  705. hydpy/models/gland/gland_outlets.py +11 -0
  706. hydpy/models/gland/gland_states.py +90 -0
  707. hydpy/models/gland_gr4.py +501 -0
  708. hydpy/models/gland_gr5.py +463 -0
  709. hydpy/models/gland_gr6.py +487 -0
  710. hydpy/models/hland/__init__.py +20 -0
  711. hydpy/models/hland/hland_aides.py +19 -0
  712. hydpy/models/hland/hland_constants.py +37 -0
  713. hydpy/models/hland/hland_control.py +1530 -0
  714. hydpy/models/hland/hland_derived.py +683 -0
  715. hydpy/models/hland/hland_factors.py +57 -0
  716. hydpy/models/hland/hland_fixed.py +42 -0
  717. hydpy/models/hland/hland_fluxes.py +279 -0
  718. hydpy/models/hland/hland_inputs.py +19 -0
  719. hydpy/models/hland/hland_masks.py +107 -0
  720. hydpy/models/hland/hland_model.py +4664 -0
  721. hydpy/models/hland/hland_outlets.py +11 -0
  722. hydpy/models/hland/hland_parameters.py +227 -0
  723. hydpy/models/hland/hland_sequences.py +382 -0
  724. hydpy/models/hland/hland_states.py +236 -0
  725. hydpy/models/hland_96.py +1812 -0
  726. hydpy/models/hland_96c.py +1196 -0
  727. hydpy/models/hland_96p.py +1204 -0
  728. hydpy/models/kinw/__init__.py +18 -0
  729. hydpy/models/kinw/kinw_aides.py +306 -0
  730. hydpy/models/kinw/kinw_control.py +270 -0
  731. hydpy/models/kinw/kinw_derived.py +197 -0
  732. hydpy/models/kinw/kinw_fixed.py +33 -0
  733. hydpy/models/kinw/kinw_fluxes.py +37 -0
  734. hydpy/models/kinw/kinw_inlets.py +11 -0
  735. hydpy/models/kinw/kinw_model.py +3026 -0
  736. hydpy/models/kinw/kinw_outlets.py +11 -0
  737. hydpy/models/kinw/kinw_solver.py +45 -0
  738. hydpy/models/kinw/kinw_states.py +17 -0
  739. hydpy/models/kinw_williams.py +1299 -0
  740. hydpy/models/kinw_williams_ext.py +768 -0
  741. hydpy/models/lland/__init__.py +42 -0
  742. hydpy/models/lland/lland_aides.py +38 -0
  743. hydpy/models/lland/lland_constants.py +88 -0
  744. hydpy/models/lland/lland_control.py +1329 -0
  745. hydpy/models/lland/lland_derived.py +380 -0
  746. hydpy/models/lland/lland_factors.py +18 -0
  747. hydpy/models/lland/lland_fixed.py +128 -0
  748. hydpy/models/lland/lland_fluxes.py +626 -0
  749. hydpy/models/lland/lland_inlets.py +12 -0
  750. hydpy/models/lland/lland_inputs.py +33 -0
  751. hydpy/models/lland/lland_logs.py +17 -0
  752. hydpy/models/lland/lland_masks.py +212 -0
  753. hydpy/models/lland/lland_model.py +7690 -0
  754. hydpy/models/lland/lland_outlets.py +12 -0
  755. hydpy/models/lland/lland_parameters.py +195 -0
  756. hydpy/models/lland/lland_sequences.py +67 -0
  757. hydpy/models/lland/lland_states.py +280 -0
  758. hydpy/models/lland_dd.py +2270 -0
  759. hydpy/models/lland_knauf.py +2156 -0
  760. hydpy/models/lland_knauf_ic.py +1920 -0
  761. hydpy/models/meteo/__init__.py +12 -0
  762. hydpy/models/meteo/meteo_control.py +154 -0
  763. hydpy/models/meteo/meteo_derived.py +159 -0
  764. hydpy/models/meteo/meteo_factors.py +88 -0
  765. hydpy/models/meteo/meteo_fixed.py +19 -0
  766. hydpy/models/meteo/meteo_fluxes.py +46 -0
  767. hydpy/models/meteo/meteo_inputs.py +47 -0
  768. hydpy/models/meteo/meteo_logs.py +30 -0
  769. hydpy/models/meteo/meteo_model.py +2904 -0
  770. hydpy/models/meteo/meteo_parameters.py +14 -0
  771. hydpy/models/meteo/meteo_sequences.py +22 -0
  772. hydpy/models/meteo_clear_glob_io.py +77 -0
  773. hydpy/models/meteo_glob_fao56.py +217 -0
  774. hydpy/models/meteo_glob_io.py +68 -0
  775. hydpy/models/meteo_glob_morsim.py +444 -0
  776. hydpy/models/meteo_precip_io.py +76 -0
  777. hydpy/models/meteo_psun_sun_glob_io.py +83 -0
  778. hydpy/models/meteo_sun_fao56.py +188 -0
  779. hydpy/models/meteo_sun_morsim.py +466 -0
  780. hydpy/models/meteo_temp_io.py +76 -0
  781. hydpy/models/musk/__init__.py +15 -0
  782. hydpy/models/musk/musk_control.py +328 -0
  783. hydpy/models/musk/musk_derived.py +32 -0
  784. hydpy/models/musk/musk_factors.py +53 -0
  785. hydpy/models/musk/musk_fluxes.py +24 -0
  786. hydpy/models/musk/musk_inlets.py +11 -0
  787. hydpy/models/musk/musk_masks.py +15 -0
  788. hydpy/models/musk/musk_model.py +838 -0
  789. hydpy/models/musk/musk_outlets.py +11 -0
  790. hydpy/models/musk/musk_sequences.py +88 -0
  791. hydpy/models/musk/musk_solver.py +68 -0
  792. hydpy/models/musk/musk_states.py +64 -0
  793. hydpy/models/musk_classic.py +228 -0
  794. hydpy/models/musk_mct.py +1247 -0
  795. hydpy/models/rconc/__init__.py +12 -0
  796. hydpy/models/rconc/rconc_control.py +473 -0
  797. hydpy/models/rconc/rconc_derived.py +76 -0
  798. hydpy/models/rconc/rconc_fluxes.py +19 -0
  799. hydpy/models/rconc/rconc_logs.py +74 -0
  800. hydpy/models/rconc/rconc_model.py +260 -0
  801. hydpy/models/rconc/rconc_states.py +11 -0
  802. hydpy/models/rconc_nash.py +48 -0
  803. hydpy/models/rconc_uh.py +53 -0
  804. hydpy/models/sw1d/__init__.py +17 -0
  805. hydpy/models/sw1d/sw1d_control.py +356 -0
  806. hydpy/models/sw1d/sw1d_derived.py +85 -0
  807. hydpy/models/sw1d/sw1d_factors.py +78 -0
  808. hydpy/models/sw1d/sw1d_fixed.py +12 -0
  809. hydpy/models/sw1d/sw1d_fluxes.py +55 -0
  810. hydpy/models/sw1d/sw1d_inlets.py +17 -0
  811. hydpy/models/sw1d/sw1d_model.py +3385 -0
  812. hydpy/models/sw1d/sw1d_outlets.py +11 -0
  813. hydpy/models/sw1d/sw1d_receivers.py +11 -0
  814. hydpy/models/sw1d/sw1d_senders.py +11 -0
  815. hydpy/models/sw1d/sw1d_states.py +23 -0
  816. hydpy/models/sw1d_channel.py +2051 -0
  817. hydpy/models/sw1d_gate_out.py +599 -0
  818. hydpy/models/sw1d_lias.py +105 -0
  819. hydpy/models/sw1d_lias_sluice.py +531 -0
  820. hydpy/models/sw1d_network.py +1219 -0
  821. hydpy/models/sw1d_pump.py +448 -0
  822. hydpy/models/sw1d_q_in.py +79 -0
  823. hydpy/models/sw1d_q_out.py +81 -0
  824. hydpy/models/sw1d_storage.py +78 -0
  825. hydpy/models/sw1d_weir_out.py +75 -0
  826. hydpy/models/test/__init__.py +14 -0
  827. hydpy/models/test/test_control.py +28 -0
  828. hydpy/models/test/test_fluxes.py +17 -0
  829. hydpy/models/test/test_model.py +201 -0
  830. hydpy/models/test/test_solver.py +48 -0
  831. hydpy/models/test/test_states.py +17 -0
  832. hydpy/models/test_discontinous.py +46 -0
  833. hydpy/models/test_stiff0d.py +47 -0
  834. hydpy/models/test_stiff1d.py +42 -0
  835. hydpy/models/whmod/__init__.py +21 -0
  836. hydpy/models/whmod/whmod_constants.py +77 -0
  837. hydpy/models/whmod/whmod_control.py +333 -0
  838. hydpy/models/whmod/whmod_derived.py +210 -0
  839. hydpy/models/whmod/whmod_factors.py +9 -0
  840. hydpy/models/whmod/whmod_fluxes.py +105 -0
  841. hydpy/models/whmod/whmod_inputs.py +15 -0
  842. hydpy/models/whmod/whmod_masks.py +178 -0
  843. hydpy/models/whmod/whmod_model.py +2091 -0
  844. hydpy/models/whmod/whmod_parameters.py +155 -0
  845. hydpy/models/whmod/whmod_sequences.py +193 -0
  846. hydpy/models/whmod/whmod_states.py +73 -0
  847. hydpy/models/whmod_rural.py +794 -0
  848. hydpy/models/whmod_urban.py +1011 -0
  849. hydpy/models/wland/__init__.py +43 -0
  850. hydpy/models/wland/wland_aides.py +55 -0
  851. hydpy/models/wland/wland_constants.py +103 -0
  852. hydpy/models/wland/wland_control.py +508 -0
  853. hydpy/models/wland/wland_derived.py +330 -0
  854. hydpy/models/wland/wland_factors.py +11 -0
  855. hydpy/models/wland/wland_fixed.py +12 -0
  856. hydpy/models/wland/wland_fluxes.py +166 -0
  857. hydpy/models/wland/wland_inputs.py +33 -0
  858. hydpy/models/wland/wland_masks.py +54 -0
  859. hydpy/models/wland/wland_model.py +3755 -0
  860. hydpy/models/wland/wland_outlets.py +11 -0
  861. hydpy/models/wland/wland_parameters.py +214 -0
  862. hydpy/models/wland/wland_sequences.py +108 -0
  863. hydpy/models/wland/wland_solver.py +45 -0
  864. hydpy/models/wland/wland_states.py +56 -0
  865. hydpy/models/wland_gd.py +888 -0
  866. hydpy/models/wland_wag.py +1244 -0
  867. hydpy/models/wq/__init__.py +14 -0
  868. hydpy/models/wq/wq_control.py +117 -0
  869. hydpy/models/wq/wq_derived.py +182 -0
  870. hydpy/models/wq/wq_factors.py +79 -0
  871. hydpy/models/wq/wq_fluxes.py +17 -0
  872. hydpy/models/wq/wq_model.py +1889 -0
  873. hydpy/models/wq_trapeze.py +168 -0
  874. hydpy/models/wq_trapeze_strickler.py +101 -0
  875. hydpy/models/wq_walrus.py +57 -0
  876. hydpy/py.typed +0 -0
  877. hydpy/tests/.coveragerc +22 -0
  878. hydpy/tests/__init__.py +0 -0
  879. hydpy/tests/check_consistency.py +32 -0
  880. hydpy/tests/hydpydoctestcustomize.pth +1 -0
  881. hydpy/tests/hydpydoctestcustomize.py +15 -0
  882. hydpy/tests/iotesting/__init__.py +0 -0
  883. hydpy/tests/run_doctests.py +233 -0
  884. hydpy-6.2.dev1.data/scripts/hyd.py +277 -0
  885. hydpy-6.2.dev1.dist-info/LICENSE +165 -0
  886. hydpy-6.2.dev1.dist-info/METADATA +163 -0
  887. hydpy-6.2.dev1.dist-info/RECORD +890 -0
  888. hydpy-6.2.dev1.dist-info/WHEEL +5 -0
  889. hydpy-6.2.dev1.dist-info/licenses_hydpy_installer.txt +42 -0
  890. hydpy-6.2.dev1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1571 @@
1
+ """This module implements tools for defining subsets of |Node| and |Element| objects of
2
+ large *HydPy* projects, called "selections"."""
3
+
4
+ # import...
5
+ # ...from standard library
6
+ from __future__ import annotations
7
+ import collections
8
+ import copy
9
+ import itertools
10
+ import types
11
+
12
+ # ...from site-packages
13
+ import black
14
+ import networkx
15
+
16
+ # ...from HydPy
17
+ import hydpy
18
+ from hydpy.core import devicetools
19
+ from hydpy.core import hydpytools
20
+ from hydpy.core import importtools
21
+ from hydpy.core import modeltools
22
+ from hydpy.core import objecttools
23
+ from hydpy.core.typingtools import *
24
+
25
+ ModelTypesArg: TypeAlias = Union[modeltools.Model, types.ModuleType, str]
26
+
27
+
28
+ class Selections:
29
+ """Collection class for |Selection| objects.
30
+
31
+ You can pass an arbitrary number of |Selection| objects to the constructor of class
32
+ |Selections|:
33
+
34
+ >>> sel1 = Selection("sel1", ["node1", "node2"], ["element1"])
35
+ >>> sel2 = Selection("sel2", ["node1", "node3"], ["element2"])
36
+ >>> selections = Selections(sel1, sel2)
37
+ >>> selections
38
+ Selections("sel1", "sel2")
39
+
40
+ Also, you can query, add, and remove |Selection| objects via attribute access:
41
+
42
+ >>> selections.sel3 # doctest: +ELLIPSIS
43
+ Traceback (most recent call last):
44
+ ...
45
+ AttributeError: The actual Selections object handles neither a normal attribute \
46
+ nor a Selection object called `sel3`...
47
+ >>> sel3 = Selection("sel3", ["node1", "node4"], ["element3"])
48
+ >>> selections.sel3 = sel3
49
+ >>> selections.sel3
50
+ Selection("sel3",
51
+ nodes=("node1", "node4"),
52
+ elements="element3")
53
+ >>> "sel3" in dir(selections)
54
+ True
55
+ >>> del selections.sel3
56
+ >>> "sel3" in dir(selections)
57
+ False
58
+ >>> del selections.sel3
59
+ Traceback (most recent call last):
60
+ ...
61
+ AttributeError: The actual Selections object handles neither a normal attribute \
62
+ nor a Selection object called `sel3` that could be deleted.
63
+
64
+ Attribute names must be consistent with the `name` attribute of the respective
65
+ |Selection| object:
66
+
67
+ >>> selections.sel4 = sel3
68
+ Traceback (most recent call last):
69
+ ...
70
+ ValueError: To avoid inconsistencies when handling Selection objects as \
71
+ attributes of a Selections object, attribute name and Selection name must be \
72
+ identical. However, for selection `sel3` the given attribute name is `sel4`.
73
+
74
+ You can use item access alternatively:
75
+
76
+ >>> selections["sel4"]
77
+ Traceback (most recent call last):
78
+ ...
79
+ KeyError: 'The actual Selections object does not handle a Selection object called \
80
+ `sel4`.'
81
+ >>> selections["sel4"] = Selection("sel4")
82
+ >>> selections["sel4"]
83
+ Selection("sel4",
84
+ nodes=(),
85
+ elements=())
86
+ >>> del selections["sel4"]
87
+ >>> del selections["sel4"]
88
+ Traceback (most recent call last):
89
+ ...
90
+ KeyError: 'The actual Selections object does not handle a Selection object called \
91
+ `sel4` that could be deleted.'
92
+
93
+ You can ask for the existence of specific |Selection| objects within a |Selections|
94
+ object both via its name and via the object itself:
95
+
96
+ >>> sel1 in selections
97
+ True
98
+ >>> "sel1" in selections
99
+ True
100
+ >>> sel3 in selections
101
+ False
102
+ >>> "sel3" in selections
103
+ False
104
+
105
+ Class |Selections| supports both the |iter| and |len| operators:
106
+
107
+ >>> for selection in selections:
108
+ ... print(selection.name)
109
+ sel1
110
+ sel2
111
+ >>> len(selections)
112
+ 2
113
+
114
+ For convenience, use the "+", "-", "+=", and "-=" operators to compare and modify
115
+ |Selections| objects either based on single |Selection| objects or collections of
116
+ |Selection| objects:
117
+
118
+ >>> larger = selections + sel3
119
+ >>> smaller = selections - sel2
120
+ >>> sorted(selections.names)
121
+ ['sel1', 'sel2']
122
+ >>> sorted(larger.names)
123
+ ['sel1', 'sel2', 'sel3']
124
+ >>> smaller.names
125
+ ('sel1',)
126
+
127
+ >>> smaller += larger
128
+ >>> sorted(smaller.names)
129
+ ['sel1', 'sel2', 'sel3']
130
+ >>> smaller -= sel1, sel2
131
+ >>> smaller.names
132
+ ('sel3',)
133
+
134
+ Note that trying to remove non-existing |Selection| objects does not raise errors:
135
+
136
+ >>> smaller -= sel2
137
+ >>> smaller.names
138
+ ('sel3',)
139
+ >>> smaller - (sel1, sel2, sel3)
140
+ Selections()
141
+
142
+ The binary operators do not support types other than the mentioned ones:
143
+
144
+ >>> smaller -= "sel3"
145
+ Traceback (most recent call last):
146
+ ...
147
+ TypeError: Binary operations on Selections objects are defined for other \
148
+ Selections objects, single Selection objects, or iterables containing `Selection` \
149
+ objects, but the type of the given argument is `str`.
150
+ >>> smaller -= 1 # doctest: +ELLIPSIS
151
+ Traceback (most recent call last):
152
+ ...
153
+ TypeError: ... is `int`.
154
+
155
+ Use the "==" operator to compare two |Selections| objects:
156
+
157
+ >>> larger == smaller
158
+ False
159
+ >>> larger == (smaller + selections)
160
+ True
161
+ >>> larger == (sel1, sel2, sel3)
162
+ False
163
+ """
164
+
165
+ def __init__(self, *selections: Selection) -> None:
166
+ self.__selections: dict[str, Selection] = {}
167
+ self.add_selections(*selections)
168
+
169
+ @property
170
+ def names(self) -> tuple[str, ...]:
171
+ """The names of the actual |Selection| objects.
172
+
173
+ >>> from hydpy import Selection, Selections
174
+ >>> selections = Selections(
175
+ ... Selection("sel1", ["node1", "node2"], ["element1"]),
176
+ ... Selection("sel2", ["node1", "node3"], ["element2"]))
177
+ >>> sorted(selections.names)
178
+ ['sel1', 'sel2']
179
+ """
180
+ return tuple(self.__selections.keys())
181
+
182
+ @property
183
+ def nodes(self) -> devicetools.Nodes:
184
+ """The |Node| objects of all handled |Selection| objects.
185
+
186
+ >>> from hydpy import Selection, Selections
187
+ >>> selections = Selections(
188
+ ... Selection("sel1", ["node1", "node2"], ["element1"]),
189
+ ... Selection("sel2", ["node1", "node3"], ["element2"]))
190
+ >>> selections.nodes
191
+ Nodes("node1", "node2", "node3")
192
+ """
193
+ nodes = devicetools.Nodes()
194
+ for selection in self:
195
+ nodes += selection.nodes
196
+ return nodes
197
+
198
+ @property
199
+ def elements(self) -> devicetools.Elements:
200
+ """The |Element| objects of all handled |Selection| objects.
201
+
202
+ >>> from hydpy import Selection, Selections
203
+ >>> selections = Selections(
204
+ ... Selection("sel1", ["node1"], ["element1"]),
205
+ ... Selection("sel2", ["node1"], ["element2", "element3"]))
206
+ >>> selections.elements
207
+ Elements("element1", "element2", "element3")
208
+ """
209
+ elements = devicetools.Elements()
210
+ for selection in self:
211
+ elements += selection.elements
212
+ return elements
213
+
214
+ @property
215
+ def complete(self) -> Selection:
216
+ """An automatically created selection that comprises the nodes and elements of
217
+ all currently available, user-defined selections.
218
+
219
+ >>> from hydpy import Selection, Selections
220
+ >>> selections = Selections(
221
+ ... Selection("sel1", ["node1"], ["element1"]),
222
+ ... Selection("sel2", ["node1"], ["element2", "element3"]))
223
+ >>> selections.complete
224
+ Selection("complete",
225
+ nodes="node1",
226
+ elements=("element1", "element2", "element3"))
227
+
228
+ The selection |Selections.complete| is always freshly created and so reflects
229
+ the current state |Selections| instance:
230
+
231
+ >>> selections.sel1.nodes.add_device("node2")
232
+ >>> selections.complete
233
+ Selection("complete",
234
+ nodes=("node1", "node2"),
235
+ elements=("element1", "element2", "element3"))
236
+
237
+ Therefore, changing the |Selection| object returned by property
238
+ |Selections.complete| does neither change the |Selections| object nor
239
+ subsequentially returned |Selections.complete| selections:
240
+
241
+ >>> selections.complete.nodes.add_device("node3")
242
+ >>> assert "node3" not in selections.nodes
243
+ >>> selections.complete
244
+ Selection("complete",
245
+ nodes=("node1", "node2"),
246
+ elements=("element1", "element2", "element3"))
247
+
248
+ Item access is provided:
249
+
250
+ >>> assert selections["complete"] == selections.complete
251
+
252
+ Selection |Selections.complete| is ignored when iterating through the
253
+ user-defined selections:
254
+
255
+ >>> assert len(selections) == 2
256
+ """
257
+ return Selection("complete", nodes=self.nodes, elements=self.elements)
258
+
259
+ def add_selections(self, *selections: Selection) -> None:
260
+ """Add the given |Selection| object(s) to the current |Selections| object.
261
+
262
+ >>> from hydpy import Selection, Selections
263
+ >>> selections = Selections(Selection("sel1", ["node1"], ["element1"]))
264
+ >>> selections.add_selections(
265
+ ... Selection("sel2", ["node1"], ["element2", "element3"]),
266
+ ... Selection("sel3", ["node2"], []))
267
+ >>> selections
268
+ Selections("sel1", "sel2", "sel3")
269
+ >>> selections.nodes
270
+ Nodes("node1", "node2")
271
+ >>> selections.elements
272
+ Elements("element1", "element2", "element3")
273
+
274
+ |Selections| rejects any |Selection| objects named `complete` to avoid conflicts
275
+ with the automatically created |Selections.complete| selection:
276
+
277
+ >>> selections.add_selections(Selection("complete"))
278
+ Traceback (most recent call last):
279
+ ...
280
+ ValueError: You cannot assign a selection with the name `complete` to a \
281
+ `Selections` object because it would conflict with the selection automatically \
282
+ created by its property `Selections.complete`.
283
+ """
284
+ for selection in selections:
285
+ if selection.name == "complete":
286
+ raise ValueError(
287
+ "You cannot assign a selection with the name `complete` to a "
288
+ "`Selections` object because it would conflict with the selection "
289
+ "automatically created by its property `Selections.complete`."
290
+ )
291
+ self.__selections[selection.name] = selection
292
+
293
+ def remove_selections(self, *selections: Selection) -> None:
294
+ """Remove the given |Selection| object(s) from the current |Selections| object.
295
+
296
+ >>> from hydpy import Selection, Selections
297
+ >>> selections = Selections(
298
+ ... Selection("sel1", ["node1"], ["element1"]),
299
+ ... Selection("sel2", ["node1"], ["element2", "element3"]))
300
+ >>> selections.remove_selections(
301
+ ... Selection("sel3", ["node2"], []), selections["sel1"])
302
+ >>> selections
303
+ Selections("sel2")
304
+ >>> selections.nodes
305
+ Nodes("node1")
306
+ >>> selections.elements
307
+ Elements("element2", "element3")
308
+ """
309
+ for selection in selections:
310
+ try:
311
+ del self[selection.name]
312
+ except KeyError:
313
+ pass
314
+
315
+ def find(self, device: devicetools.NodeOrElement) -> Selections:
316
+ """Return all |Selection| objects containing the given |Node| or |Element|
317
+ object.
318
+
319
+ >>> from hydpy import Elements, Nodes, Selection, Selections
320
+ >>> nodes = Nodes("n1", "n2", "n3")
321
+ >>> elements = Elements("e1", "e2")
322
+ >>> selections = Selections(
323
+ ... Selection("s1", ["n1", "n2"], ["e1"]),
324
+ ... Selection("s2", ["n1"]))
325
+ >>> selections.find(nodes.n1)
326
+ Selections("s1", "s2")
327
+ >>> selections.find(nodes.n2)
328
+ Selections("s1")
329
+ >>> selections.find(nodes.n3)
330
+ Selections()
331
+ >>> selections.find(elements.e1)
332
+ Selections("s1")
333
+ >>> selections.find(elements.e2)
334
+ Selections()
335
+ """
336
+ attr = "nodes" if isinstance(device, devicetools.Node) else "elements"
337
+ selections = (
338
+ selection for selection in self if device in getattr(selection, attr)
339
+ )
340
+ return Selections(*selections)
341
+
342
+ @overload
343
+ def query_intersections(
344
+ self, selection2element: Literal[True] = ...
345
+ ) -> dict[Selection, dict[Selection, devicetools.Elements]]: ...
346
+
347
+ @overload
348
+ def query_intersections(
349
+ self, selection2element: Literal[False]
350
+ ) -> dict[devicetools.Element, Selections]: ...
351
+
352
+ def query_intersections(
353
+ self, selection2element: bool = True
354
+ ) -> (
355
+ dict[Selection, dict[Selection, devicetools.Elements]]
356
+ | dict[devicetools.Element, Selections]
357
+ ):
358
+ """A dictionary covering all cases where one |Element| object is a member of
359
+ multiple |Selection| objects.
360
+
361
+ The dictionary's structure depends on the value of the optional argument
362
+ `selection2element`. See method |Selections.print_intersections| for an
363
+ example.
364
+ """
365
+ if selection2element:
366
+ intersections: dict[Selection, dict[Selection, devicetools.Elements]] = (
367
+ collections.defaultdict(dict)
368
+ )
369
+ for selection1, selection2 in itertools.combinations(self, 2):
370
+ intersection = selection1.elements.intersection(*selection2.elements)
371
+ if intersection:
372
+ intersections[selection1][selection2] = intersection
373
+ intersections[selection2][selection1] = intersection
374
+ return dict(intersections)
375
+ intersections_: dict[devicetools.Element, Selections] = {}
376
+ for element in self.elements:
377
+ selections = self.find(element)
378
+ if len(selections) > 1:
379
+ intersections_[element] = selections
380
+ return intersections_
381
+
382
+ def print_intersections(self, selection2element: bool = True) -> None:
383
+ """Print the result of method |Selections.query_intersections|.
384
+
385
+ We use method |Selections.print_intersections| to check if any combination of
386
+ the following selections handles the same elements.
387
+
388
+ >>> from hydpy import Selection, Selections
389
+ >>> selections = Selections(
390
+ ... Selection("s1", nodes="n1",elements=("e1", "e2", "e3")),
391
+ ... Selection("s2", nodes="n1", elements=("e2", "e3", "e4")),
392
+ ... Selection("s3", nodes="n1", elements="e3"),
393
+ ... Selection("s4", nodes="n1", elements=("e5", "e6")),
394
+ ... )
395
+
396
+ If we call method |Selections.print_intersections| with argument
397
+ `selection2element` |True|, we find out which selection intersects with which
398
+ other and which elements are affected:
399
+
400
+ >>> selections.print_intersections()
401
+ selection s1 intersects with...
402
+ ...selection s2 due to the following elements: e2 and e3
403
+ ...selection s3 due to the following elements: e3
404
+ selection s2 intersects with...
405
+ ...selection s1 due to the following elements: e2 and e3
406
+ ...selection s3 due to the following elements: e3
407
+ selection s3 intersects with...
408
+ ...selection s1 due to the following elements: e3
409
+ ...selection s2 due to the following elements: e3
410
+
411
+ If we call method |Selections.print_intersections| with argument
412
+ `selection2element` |False|, we find out which element occurs multiple times in
413
+ which selections:
414
+
415
+ >>> selections.print_intersections(selection2element=False)
416
+ element e2 is a member of multiple selections: s1 and s2
417
+ element e3 is a member of multiple selections: s1, s2, and s3
418
+ """
419
+ if selection2element:
420
+ intersections = self.query_intersections(True)
421
+ for selection1, selection2elements in intersections.items():
422
+ print("selection", selection1, "intersects with...")
423
+ for selection2, elements in selection2elements.items():
424
+ print(
425
+ " ...selection",
426
+ selection2,
427
+ "due to the following elements:",
428
+ objecttools.enumeration(elements.names),
429
+ )
430
+ else:
431
+ intersections_ = self.query_intersections(False)
432
+ for element, selections in intersections_.items():
433
+ print(
434
+ "element",
435
+ element.name,
436
+ "is a member of multiple selections:",
437
+ objecttools.enumeration(selections.names),
438
+ )
439
+
440
+ def __getattr__(self, key: str) -> Selection:
441
+ try:
442
+ return self.__selections[key]
443
+ except KeyError:
444
+ raise AttributeError(
445
+ f"The actual Selections object handles neither a normal attribute nor "
446
+ f"a Selection object called `{key}`."
447
+ ) from None
448
+
449
+ def __setattr__(self, name: str, value: object) -> None:
450
+ if isinstance(value, Selection):
451
+ self[name] = value
452
+ else:
453
+ super().__setattr__(name, value)
454
+
455
+ def __delattr__(self, key: str) -> None:
456
+ try:
457
+ del self.__selections[key]
458
+ except KeyError:
459
+ raise AttributeError(
460
+ f"The actual Selections object handles neither a normal attribute nor "
461
+ f"a Selection object called `{key}` that could be deleted."
462
+ ) from None
463
+
464
+ def __getitem__(self, key: str) -> Selection:
465
+ if key == "complete":
466
+ return self.complete
467
+ try:
468
+ return self.__selections[key]
469
+ except KeyError:
470
+ raise KeyError(
471
+ f"The actual Selections object does not handle a Selection object "
472
+ f"called `{key}`."
473
+ ) from None
474
+
475
+ def __setitem__(self, key: str, value: Selection) -> None:
476
+ if key != value.name:
477
+ raise ValueError(
478
+ f"To avoid inconsistencies when handling Selection objects as "
479
+ f"attributes of a Selections object, attribute name and Selection "
480
+ f"name must be identical. However, for selection `{value.name}` the "
481
+ f"given attribute name is `{key}`."
482
+ )
483
+ self.add_selections(value)
484
+
485
+ def __delitem__(self, key: str) -> None:
486
+ try:
487
+ del self.__selections[key]
488
+ except KeyError:
489
+ raise KeyError(
490
+ f"The actual Selections object does not handle a Selection object "
491
+ f"called `{key}` that could be deleted."
492
+ ) from None
493
+
494
+ def __contains__(self, value: str | Selection) -> bool:
495
+ if isinstance(value, str):
496
+ return value in self.names
497
+ return value in self.__selections.values()
498
+
499
+ def __iter__(self) -> Iterator[Selection]:
500
+ return iter(self.__selections.values())
501
+
502
+ def __len__(self) -> int:
503
+ return len(self.__selections)
504
+
505
+ @staticmethod
506
+ def __getiterable(value: Mayberable1[Selection]) -> list[Selection]:
507
+ """Try to convert the given argument to a |list| of |Selection| objects and
508
+ return it."""
509
+ try:
510
+ return list(objecttools.extract(value, (Selection,)))
511
+ except TypeError:
512
+ raise TypeError(
513
+ f"Binary operations on Selections objects are defined for other "
514
+ f"Selections objects, single Selection objects, or iterables "
515
+ f"containing `Selection` objects, but the type of the given argument "
516
+ f"is `{type(value).__name__}`."
517
+ ) from None
518
+
519
+ def __add__(self, other: Mayberable1[Selection]) -> Selections:
520
+ new = copy.copy(self)
521
+ new.add_selections(*self.__getiterable(other))
522
+ return new
523
+
524
+ def __iadd__(self, other: Mayberable1[Selection]) -> Selections:
525
+ self.add_selections(*self.__getiterable(other))
526
+ return self
527
+
528
+ def __sub__(self, other: Mayberable1[Selection]) -> Selections:
529
+ selections = self.__getiterable(other)
530
+ new = copy.copy(self)
531
+ for selection in selections:
532
+ try:
533
+ del new[selection.name]
534
+ except KeyError:
535
+ pass
536
+ return new
537
+
538
+ def __isub__(self, other: Mayberable1[Selection]) -> Selections:
539
+ selections = self.__getiterable(other)
540
+ for selection in selections:
541
+ try:
542
+ del self[selection.name]
543
+ except KeyError:
544
+ pass
545
+ return self
546
+
547
+ def __eq__(self, other: object) -> bool:
548
+ if isinstance(other, (Selection, Selections, hydpytools.HydPy)):
549
+ return (self.nodes == self.nodes) and (self.elements == other.elements)
550
+ return False
551
+
552
+ def __copy__(self) -> Selections:
553
+ return type(self)(*self.__selections.values())
554
+
555
+ def __repr__(self) -> str:
556
+ return self.assignrepr("")
557
+
558
+ def assignrepr(self, prefix: str = "") -> str:
559
+ """Return a |repr| string with a prefixed assignment."""
560
+ with objecttools.repr_.preserve_strings(True):
561
+ options = hydpy.pub.options
562
+ with options.ellipsis(2, optional=True):
563
+ prefix = f"{prefix}{type(self).__name__}("
564
+ return (
565
+ f"{objecttools.assignrepr_values(sorted(self.names), prefix, 70)})"
566
+ )
567
+
568
+ def __dir__(self) -> list[str]:
569
+ return cast(list[str], super().__dir__()) + list(self.names)
570
+
571
+
572
+ class Selection:
573
+ """Handles and modifies combinations of |Node| and |Element| objects.
574
+
575
+ In *HydPy*, |Node|, and |Element| objects are the fundamental means to structure
576
+ projects. However, keeping the overview of huge projects involving thousands of
577
+ nodes and elements requires additional strategies.
578
+
579
+ One such strategy is to define different instances of class |Selection| for
580
+ different aspects of a project. Often, a selection contains all nodes and elements
581
+ of a certain subcatchment or all elements handling certain model types. Selections
582
+ can be overlapping, meaning, for example, that an element can be part of a
583
+ subcatchment selection and of model-type selection at the same time.
584
+
585
+ Selections can be written to and read from individual network files, as explained
586
+ in the documentation on class |NetworkManager|. Read selections are available via
587
+ the |pub| module. In most application scripts (e.g. for parameter calibration),
588
+ one performs different operations on the nodes and elements of the different
589
+ selections (e.g. change parameter "a" and "b" for models of selection "x" and "y",
590
+ respectively). However, class |Selection| also provides features for creating
591
+ combinations of |Node| and |Element| objects suitable for different tasks, as
592
+ explained in the documentation of the respective methods. Here we only show its
593
+ basic usage with the help of the `HydPy-H-Lahn` example project prepared by
594
+ function |prepare_full_example_2|:
595
+
596
+ >>> from hydpy.core.testtools import prepare_full_example_2
597
+ >>> _, pub, _ = prepare_full_example_2()
598
+
599
+ For example, `HydPy-H-Lahn` defines a `headwaters` selection:
600
+
601
+ >>> pub.selections.headwaters
602
+ Selection("headwaters",
603
+ nodes=("dill_assl", "lahn_marb"),
604
+ elements=("land_dill_assl", "land_lahn_marb"))
605
+
606
+ You can compare this selection with other new or already available selections, with
607
+ "headwaters < complete" returning |True| meaning that all nodes and elements of the
608
+ headwater catchments are also part of the entire catchment:
609
+
610
+ >>> from hydpy import Selection
611
+ >>> test = Selection("test",
612
+ ... elements=("land_dill_assl", "land_lahn_marb"),
613
+ ... nodes=("dill_assl", "lahn_marb"))
614
+ >>> pub.selections.headwaters < test
615
+ False
616
+ >>> pub.selections.headwaters <= test
617
+ True
618
+ >>> pub.selections.headwaters == test
619
+ True
620
+ >>> pub.selections.headwaters != test
621
+ False
622
+ >>> pub.selections.headwaters >= test
623
+ True
624
+ >>> pub.selections.headwaters > test
625
+ False
626
+ >>> pub.selections.headwaters < pub.selections.complete
627
+ True
628
+ >>> pub.selections.headwaters <= pub.selections.complete
629
+ True
630
+ >>> pub.selections.headwaters == pub.selections.complete
631
+ False
632
+ >>> pub.selections.headwaters != pub.selections.complete
633
+ True
634
+ >>> pub.selections.headwaters >= pub.selections.complete
635
+ False
636
+ >>> pub.selections.headwaters > pub.selections.complete
637
+ False
638
+
639
+ The |len| operator returns the total number of handled node and element objects:
640
+
641
+ >>> len(test)
642
+ 4
643
+
644
+ Use the "+=" and "-=" operators to add or remove nodes and elements:
645
+
646
+ >>> test += pub.selections.complete
647
+ >>> len(test)
648
+ 11
649
+ >>> test -= pub.selections.complete
650
+ >>> len(test)
651
+ 0
652
+
653
+ Passing a wrong argument to the binary operators results in errors like the
654
+ following:
655
+
656
+ >>> test += 1
657
+ Traceback (most recent call last):
658
+ ...
659
+ AttributeError: While trying to add selection `test` with object `1` of type \
660
+ `int`, the following error occurred: 'int' object has no attribute 'nodes'
661
+ >>> test -= pub.selections.complete.nodes.dill_assl
662
+ Traceback (most recent call last):
663
+ ...
664
+ AttributeError: While trying to subtract selection `test` with object `dill_assl` \
665
+ of type `Node`, the following error occurred: 'Node' object has no attribute 'nodes'
666
+ >>> test < "wrong"
667
+ Traceback (most recent call last):
668
+ ...
669
+ AttributeError: While trying to compare selection `test` with object `wrong` of \
670
+ type `str`, the following error occurred: 'str' object has no attribute 'nodes'
671
+
672
+ But as usual, checking for equality or inequality returns |False| and |True| for
673
+ uncomparable objects:
674
+
675
+ >>> test == "wrong"
676
+ False
677
+ >>> test != "wrong"
678
+ True
679
+
680
+ Applying the |str| function only returns the selection name:
681
+
682
+ >>> str(test)
683
+ 'test'
684
+ """
685
+
686
+ name: str
687
+ """The selection's name."""
688
+ nodes: devicetools.Nodes
689
+ """The explicitly handled |Node| objects (m).
690
+
691
+ |Selection.nodes| does not necessarily contain all nodes to which the elements in
692
+ |Selection.elements| are linked.
693
+ """
694
+ elements: devicetools.Elements
695
+ """The explicitly handled |Element| objects.
696
+
697
+ |Selection.elements| does not necessarily contain all nodes to which the elements
698
+ in |Selection.nodes| are linked.
699
+ """
700
+
701
+ def __init__(
702
+ self,
703
+ name: str,
704
+ nodes: devicetools.NodesConstrArg = None,
705
+ elements: devicetools.ElementsConstrArg = None,
706
+ ) -> None:
707
+ self.name = str(name)
708
+ self.nodes = devicetools.Nodes(nodes).copy()
709
+ self.elements = devicetools.Elements(elements).copy()
710
+
711
+ def _check_device(
712
+ self, device: devicetools.TypeNodeElement, type_of_device: str
713
+ ) -> devicetools.TypeNodeElement:
714
+ if isinstance(device, devicetools.Node):
715
+ return self.nodes[device.name]
716
+ if isinstance(device, devicetools.Element):
717
+ return self.elements[device.name]
718
+ raise TypeError(
719
+ f"Either a `Node` or an `Element` object is required as the "
720
+ f'"{type_of_device} device", but the given `device` value is of type '
721
+ f"`{type(device).__name__}`."
722
+ )
723
+
724
+ def search_upstream(
725
+ self,
726
+ device: devicetools.NodeOrElement,
727
+ name: str = "upstream",
728
+ inclusive: bool = True,
729
+ ) -> Selection:
730
+ """Return the network upstream of the given starting point, including the
731
+ starting point itself.
732
+
733
+ >>> from hydpy.core.testtools import prepare_full_example_2
734
+ >>> hp, pub, _ = prepare_full_example_2()
735
+
736
+ You can pass both |Node| and |Element| objects and, optionally, the name of the
737
+ newly created |Selection| object:
738
+
739
+ >>> test = pub.selections.complete.copy("test")
740
+ >>> test.search_upstream(hp.nodes.lahn_leun)
741
+ Selection("upstream",
742
+ nodes=("dill_assl", "lahn_leun", "lahn_marb"),
743
+ elements=("land_dill_assl", "land_lahn_leun",
744
+ "land_lahn_marb", "stream_dill_assl_lahn_leun",
745
+ "stream_lahn_marb_lahn_leun"))
746
+ >>> test.search_upstream(hp.elements.stream_lahn_marb_lahn_leun, "UPSTREAM")
747
+ Selection("UPSTREAM",
748
+ nodes=("lahn_leun", "lahn_marb"),
749
+ elements=("land_lahn_marb", "stream_lahn_marb_lahn_leun"))
750
+
751
+ Method |Selection.search_upstream| generally selects all |Node| objects
752
+ directly connected to any upstream |Element| object. Set the `inclusive`
753
+ argument to |False| to circumvent this:
754
+
755
+ >>> test.search_upstream(hp.elements.stream_lahn_marb_lahn_leun, "UPSTREAM",
756
+ ... False)
757
+ Selection("UPSTREAM",
758
+ nodes="lahn_marb",
759
+ elements=("land_lahn_marb", "stream_lahn_marb_lahn_leun"))
760
+
761
+ Wrong device specifications result in errors like the following:
762
+
763
+ >>> test.search_upstream(1)
764
+ Traceback (most recent call last):
765
+ ...
766
+ TypeError: While trying to determine an upstream network of selection `test`, \
767
+ the following error occurred: Either a `Node` or an `Element` object is required as \
768
+ the "outlet device", but the given `device` value is of type `int`.
769
+
770
+ >>> pub.selections.headwaters.search_upstream(hp.nodes.lahn_kalk)
771
+ Traceback (most recent call last):
772
+ ...
773
+ KeyError: "While trying to determine an upstream network of selection \
774
+ `headwaters`, the following error occurred: 'No node named `lahn_kalk` available.'"
775
+
776
+ Method |Selection.select_upstream| restricts the current selection to the one
777
+ determined with the method |Selection.search_upstream|:
778
+
779
+ >>> test.select_upstream(hp.nodes.lahn_leun)
780
+ Selection("test",
781
+ nodes=("dill_assl", "lahn_leun", "lahn_marb"),
782
+ elements=("land_dill_assl", "land_lahn_leun",
783
+ "land_lahn_marb", "stream_dill_assl_lahn_leun",
784
+ "stream_lahn_marb_lahn_leun"))
785
+
786
+ On the contrary, the method |Selection.deselect_upstream| restricts the current
787
+ selection to all devices not determined by method |Selection.search_upstream|:
788
+
789
+ >>> complete = pub.selections.complete.deselect_upstream(hp.nodes.lahn_leun)
790
+ >>> complete
791
+ Selection("complete",
792
+ nodes="lahn_kalk",
793
+ elements=("land_lahn_kalk", "stream_lahn_leun_lahn_kalk"))
794
+
795
+ If necessary, include the "outlet device" manually afterwards:
796
+
797
+ >>> complete.nodes.add_device(hp.nodes.lahn_leun)
798
+ >>> complete
799
+ Selection("complete",
800
+ nodes=("lahn_kalk", "lahn_leun"),
801
+ elements=("land_lahn_kalk", "stream_lahn_leun_lahn_kalk"))
802
+
803
+ Method |Selection.search_downstream| generally selects all |Node| objects
804
+ directly connected to any upstream |Element| object. Set the `inclusive`
805
+ argument to |False| to circumvent this:
806
+
807
+ >>> from hydpy import Element, Nodes, Selection
808
+ >>> nodes = Nodes(
809
+ ... "inlet", "outlet1", "outlet2", "input_", "output", "receiver", "sender")
810
+ >>> upper = Element("upper",
811
+ ... inlets=nodes.inlet, outlets=(nodes.outlet1, nodes.outlet2),
812
+ ... inputs=nodes.input_, outputs=nodes.output,
813
+ ... receivers=nodes.receiver, senders=nodes.sender)
814
+ >>> test = Selection("test", nodes=nodes, elements=upper)
815
+ >>> test.search_upstream(nodes.outlet1, inclusive=True)
816
+ Selection("upstream",
817
+ nodes=("inlet", "input_", "outlet1", "outlet2", "output",
818
+ "receiver", "sender"),
819
+ elements="upper")
820
+ >>> test.search_upstream(nodes.outlet1, inclusive=False)
821
+ Selection("upstream",
822
+ nodes=("inlet", "input_", "outlet1"),
823
+ elements="upper")
824
+ """
825
+ try:
826
+ device = self._check_device(device, "outlet")
827
+ graph = hydpytools.create_directedgraph(self.nodes, self.elements)
828
+ devices = networkx.ancestors(graph, source=device)
829
+ devices.add(device)
830
+ selection = Selection(
831
+ name=name,
832
+ nodes=[d for d in devices if isinstance(d, devicetools.Node)],
833
+ elements=[d for d in devices if isinstance(d, devicetools.Element)],
834
+ )
835
+ if inclusive:
836
+ add_device = selection.nodes.add_device
837
+ for element in selection.elements:
838
+ for nodes in (
839
+ element.outlets,
840
+ element.outputs,
841
+ element.receivers,
842
+ element.senders,
843
+ ):
844
+ for node in nodes:
845
+ add_device(node)
846
+ return selection
847
+ except BaseException:
848
+ objecttools.augment_excmessage(
849
+ f"While trying to determine an upstream network of selection "
850
+ f"`{self.name}`"
851
+ )
852
+
853
+ def select_upstream(
854
+ self, device: devicetools.NodeOrElement, inclusive: bool = True
855
+ ) -> Selection:
856
+ """Restrict the current selection to the network upstream of the given starting
857
+ point, including the starting point itself.
858
+
859
+ See the documentation on method |Selection.search_upstream| for additional
860
+ information.
861
+ """
862
+ upstream = self.search_upstream(device, inclusive=inclusive)
863
+ self.nodes = upstream.nodes
864
+ self.elements = upstream.elements
865
+ return self
866
+
867
+ def deselect_upstream(
868
+ self, device: devicetools.NodeOrElement, inclusive: bool = True
869
+ ) -> Selection:
870
+ """Remove the network upstream of the given starting point from the current
871
+ selection, including the starting point itself.
872
+
873
+ See the documentation on method |Selection.search_upstream| for additional
874
+ information.
875
+ """
876
+ upstream = self.search_upstream(device, inclusive=inclusive)
877
+ self.nodes -= upstream.nodes
878
+ self.elements -= upstream.elements
879
+ return self
880
+
881
+ def search_downstream(
882
+ self,
883
+ device: devicetools.NodeOrElement,
884
+ name: str = "downstream",
885
+ inclusive: bool = True,
886
+ ) -> Selection:
887
+ """Return the network downstream of the given starting point, including the
888
+ starting point itself.
889
+
890
+ >>> from hydpy.core.testtools import prepare_full_example_2
891
+ >>> hp, pub, _ = prepare_full_example_2()
892
+
893
+ You can pass both |Node| and |Element| objects and, optionally, the name of the
894
+ newly created |Selection| object:
895
+
896
+ >>> test = pub.selections.complete.copy("test")
897
+ >>> test.search_downstream(hp.nodes.lahn_marb)
898
+ Selection("downstream",
899
+ nodes=("lahn_kalk", "lahn_leun", "lahn_marb"),
900
+ elements=("stream_lahn_leun_lahn_kalk",
901
+ "stream_lahn_marb_lahn_leun"))
902
+ >>> test.search_downstream(hp.elements.land_lahn_marb, "DOWNSTREAM")
903
+ Selection("DOWNSTREAM",
904
+ nodes=("lahn_kalk", "lahn_leun", "lahn_marb"),
905
+ elements=("land_lahn_marb", "stream_lahn_leun_lahn_kalk",
906
+ "stream_lahn_marb_lahn_leun"))
907
+
908
+ Wrong device specifications result in errors like the following:
909
+
910
+ >>> test.search_downstream(1)
911
+ Traceback (most recent call last):
912
+ ...
913
+ TypeError: While trying to determine a downstream network of selection \
914
+ `test`, the following error occurred: Either a `Node` or an `Element` object is \
915
+ required as the "inlet device", but the given `device` value is of type `int`.
916
+
917
+ >>> pub.selections.headwaters.search_downstream(hp.nodes.lahn_kalk)
918
+ Traceback (most recent call last):
919
+ ...
920
+ KeyError: "While trying to determine a downstream network of selection \
921
+ `headwaters`, the following error occurred: 'No node named `lahn_kalk` available.'"
922
+
923
+ Method |Selection.select_downstream| restricts the current selection to the one
924
+ determined with the method |Selection.search_upstream|:
925
+
926
+ >>> test.select_downstream(hp.nodes.lahn_marb)
927
+ Selection("test",
928
+ nodes=("lahn_kalk", "lahn_leun", "lahn_marb"),
929
+ elements=("stream_lahn_leun_lahn_kalk",
930
+ "stream_lahn_marb_lahn_leun"))
931
+
932
+ On the contrary, the method |Selection.deselect_downstream| restricts the
933
+ current selection to all devices not determined by method
934
+ |Selection.search_downstream|:
935
+
936
+ >>> complete = pub.selections.complete.deselect_downstream(
937
+ ... hp.nodes.lahn_marb)
938
+ >>> complete
939
+ Selection("complete",
940
+ nodes="dill_assl",
941
+ elements=("land_dill_assl", "land_lahn_kalk",
942
+ "land_lahn_leun", "land_lahn_marb",
943
+ "stream_dill_assl_lahn_leun"))
944
+
945
+ If necessary, include the "inlet device" manually afterwards:
946
+
947
+ >>> complete.nodes.add_device(hp.nodes.lahn_marb)
948
+ >>> complete
949
+ Selection("complete",
950
+ nodes=("dill_assl", "lahn_marb"),
951
+ elements=("land_dill_assl", "land_lahn_kalk",
952
+ "land_lahn_leun", "land_lahn_marb",
953
+ "stream_dill_assl_lahn_leun"))
954
+
955
+ Method |Selection.search_downstream| generally selects all |Node| objects
956
+ directly connected to any upstream |Element| object. Set the `inclusive`
957
+ argument to |False| to circumvent this:
958
+
959
+ >>> from hydpy import Element, Nodes, Selection
960
+ >>> nodes = Nodes(
961
+ ... "inlet1", "inlet2", "outlet", "input_", "output", "receiver", "sender")
962
+ >>> lower = Element("lower",
963
+ ... inlets=(nodes.inlet1, nodes.inlet2), outlets=nodes.outlet,
964
+ ... inputs=nodes.input_, outputs=nodes.output,
965
+ ... receivers=nodes.receiver, senders=nodes.sender)
966
+ >>> test = Selection("test", nodes=nodes, elements=lower)
967
+ >>> test.search_downstream(nodes.inlet1, inclusive=True)
968
+ Selection("downstream",
969
+ nodes=("inlet1", "inlet2", "input_", "outlet", "output",
970
+ "receiver", "sender"),
971
+ elements="lower")
972
+ >>> test.search_downstream(nodes.inlet1, inclusive=False)
973
+ Selection("downstream",
974
+ nodes=("inlet1", "outlet", "output"),
975
+ elements="lower")
976
+ """
977
+ try:
978
+ device = self._check_device(device, "inlet")
979
+ graph = hydpytools.create_directedgraph(self.nodes, self.elements)
980
+ devices = networkx.descendants(graph, source=device)
981
+ devices.add(device)
982
+ selection = Selection(
983
+ name=name,
984
+ nodes=[d for d in devices if isinstance(d, devicetools.Node)],
985
+ elements=[d for d in devices if isinstance(d, devicetools.Element)],
986
+ )
987
+ if inclusive:
988
+ add_device = selection.nodes.add_device
989
+ for element in selection.elements:
990
+ for nodes in (
991
+ element.inlets,
992
+ element.inputs,
993
+ element.receivers,
994
+ element.senders,
995
+ ):
996
+ for node in nodes:
997
+ add_device(node)
998
+ return selection
999
+ except BaseException:
1000
+ objecttools.augment_excmessage(
1001
+ f"While trying to determine a downstream network of selection "
1002
+ f"`{self.name}`"
1003
+ )
1004
+
1005
+ def select_downstream(
1006
+ self, device: devicetools.NodeOrElement, inclusive: bool = True
1007
+ ) -> Selection:
1008
+ """Restrict the current selection to the network downstream of the given
1009
+ starting point, including the starting point itself.
1010
+
1011
+ See the documentation on method |Selection.search_downstream| for additional
1012
+ information.
1013
+ """
1014
+ downstream = self.search_downstream(device, inclusive=inclusive)
1015
+ self.nodes = downstream.nodes
1016
+ self.elements = downstream.elements
1017
+ return self
1018
+
1019
+ def deselect_downstream(
1020
+ self, device: devicetools.NodeOrElement, inclusive: bool = True
1021
+ ) -> Selection:
1022
+ """Remove the network downstream of the given starting point from the current
1023
+ selection, including the starting point itself.
1024
+
1025
+ See the documentation on method |Selection.search_downstream| for additional
1026
+ information.
1027
+ """
1028
+ downstream = self.search_downstream(device, inclusive=inclusive)
1029
+ self.nodes -= downstream.nodes
1030
+ self.elements -= downstream.elements
1031
+ return self
1032
+
1033
+ def search_modeltypes(
1034
+ self, *models: ModelTypesArg, name: str = "modeltypes"
1035
+ ) -> Selection:
1036
+ """Return a |Selection| object containing only the elements currently handling
1037
+ models of the given types.
1038
+
1039
+ >>> from hydpy.core.testtools import prepare_full_example_2
1040
+ >>> hp, pub, _ = prepare_full_example_2()
1041
+
1042
+ You can pass both |Model| objects and names and, as a keyword argument, the
1043
+ name of the newly created |Selection| object:
1044
+
1045
+ >>> test = pub.selections.complete.copy("test")
1046
+ >>> from hydpy import prepare_model
1047
+ >>> hland_96 = prepare_model("hland_96")
1048
+
1049
+ >>> test.search_modeltypes(hland_96)
1050
+ Selection("modeltypes",
1051
+ nodes=(),
1052
+ elements=("land_dill_assl", "land_lahn_kalk",
1053
+ "land_lahn_leun", "land_lahn_marb"))
1054
+ >>> test.search_modeltypes(
1055
+ ... hland_96, "musk_classic", "lland_dd", name="MODELTYPES")
1056
+ Selection("MODELTYPES",
1057
+ nodes=(),
1058
+ elements=("land_dill_assl", "land_lahn_kalk",
1059
+ "land_lahn_leun", "land_lahn_marb",
1060
+ "stream_dill_assl_lahn_leun",
1061
+ "stream_lahn_leun_lahn_kalk",
1062
+ "stream_lahn_marb_lahn_leun"))
1063
+
1064
+ Wrong model specifications result in errors like the following:
1065
+
1066
+ >>> test.search_modeltypes("wrong")
1067
+ Traceback (most recent call last):
1068
+ ...
1069
+ ModuleNotFoundError: While trying to determine the elements of selection \
1070
+ `test` handling the model defined by the argument(s) `wrong` of type(s) `str`, the \
1071
+ following error occurred: No module named 'hydpy.models.wrong'
1072
+
1073
+ Method |Selection.select_modeltypes| restricts the current selection to the one
1074
+ determined with the method the |Selection.search_modeltypes|:
1075
+
1076
+ >>> test.select_modeltypes(hland_96)
1077
+ Selection("test",
1078
+ nodes=(),
1079
+ elements=("land_dill_assl", "land_lahn_kalk",
1080
+ "land_lahn_leun", "land_lahn_marb"))
1081
+
1082
+ On the contrary, the method |Selection.deselect_upstream| restricts the current
1083
+ selection to all devices not determined by method the
1084
+ |Selection.search_upstream|:
1085
+
1086
+ >>> pub.selections.complete.deselect_modeltypes(hland_96)
1087
+ Selection("complete",
1088
+ nodes=(),
1089
+ elements=("stream_dill_assl_lahn_leun",
1090
+ "stream_lahn_leun_lahn_kalk",
1091
+ "stream_lahn_marb_lahn_leun"))
1092
+ """
1093
+ try:
1094
+ typelist = []
1095
+ for model in models:
1096
+ if not isinstance(model, modeltools.Model):
1097
+ model = importtools.prepare_model(model)
1098
+ typelist.append(type(model))
1099
+ typetuple = tuple(typelist)
1100
+ selection = Selection(name)
1101
+ for element in self.elements:
1102
+ if isinstance(element.model, typetuple):
1103
+ selection.elements += element
1104
+ except BaseException:
1105
+ values = objecttools.enumeration(models)
1106
+ classes = objecttools.enumeration(type(model).__name__ for model in models)
1107
+ objecttools.augment_excmessage(
1108
+ f"While trying to determine the elements of selection `{self.name}` "
1109
+ f"handling the model defined by the argument(s) `{values}` of type(s) "
1110
+ f"`{classes}`"
1111
+ )
1112
+ return selection
1113
+
1114
+ def select_modeltypes(self, *models: ModelTypesArg) -> Selection:
1115
+ """Restrict the current |Selection| object to all elements containing the given
1116
+ model types (removes all nodes).
1117
+
1118
+ See the documentation on method |Selection.search_modeltypes| for additional
1119
+ information.
1120
+ """
1121
+ self.nodes = devicetools.Nodes()
1122
+ self.elements = self.search_modeltypes(*models).elements
1123
+ return self
1124
+
1125
+ def deselect_modeltypes(self, *models: ModelTypesArg) -> Selection:
1126
+ """Restrict the current selection to all elements not containing the given
1127
+ model types (removes all nodes).
1128
+
1129
+ See the documentation on method |Selection.search_modeltypes| for additional
1130
+ information.
1131
+ """
1132
+ self.nodes = devicetools.Nodes()
1133
+ self.elements -= self.search_modeltypes(*models).elements
1134
+ return self
1135
+
1136
+ def search_nodenames(self, *substrings: str, name: str = "nodenames") -> Selection:
1137
+ """Return a new selection containing all nodes of the current selection with a
1138
+ name containing at least one of the given substrings.
1139
+
1140
+ >>> from hydpy.core.testtools import prepare_full_example_2
1141
+ >>> hp, pub, _ = prepare_full_example_2()
1142
+
1143
+ Pass the (sub)strings as positional arguments and, optionally, the name of the
1144
+ newly created |Selection| object as a keyword argument:
1145
+
1146
+ >>> test = pub.selections.complete.copy("test")
1147
+ >>> from hydpy import prepare_model
1148
+ >>> test.search_nodenames("dill_assl", "lahn_marb")
1149
+ Selection("nodenames",
1150
+ nodes=("dill_assl", "lahn_marb"),
1151
+ elements=())
1152
+
1153
+ Wrong string specifications result in errors like the following:
1154
+
1155
+ >>> test.search_nodenames(["dill_assl", "lahn_marb"])
1156
+ Traceback (most recent call last):
1157
+ ...
1158
+ TypeError: While trying to determine the nodes of selection `test` with names \
1159
+ containing at least one of the given substrings `['dill_assl', 'lahn_marb']`, the \
1160
+ following error occurred: 'in <string>' requires string as left operand, not list
1161
+
1162
+ Method |Selection.select_nodenames| restricts the current selection to the one
1163
+ determined with the the method |Selection.search_nodenames|:
1164
+
1165
+ >>> test.select_nodenames("dill_assl", "lahn_marb")
1166
+ Selection("test",
1167
+ nodes=("dill_assl", "lahn_marb"),
1168
+ elements=("land_dill_assl", "land_lahn_kalk",
1169
+ "land_lahn_leun", "land_lahn_marb",
1170
+ "stream_dill_assl_lahn_leun",
1171
+ "stream_lahn_leun_lahn_kalk",
1172
+ "stream_lahn_marb_lahn_leun"))
1173
+
1174
+ On the contrary, the method |Selection.deselect_nodenames| restricts the
1175
+ current selection to all devices not determined by the method
1176
+ |Selection.search_nodenames|:
1177
+
1178
+ >>> pub.selections.complete.deselect_nodenames("dill_assl", "lahn_marb")
1179
+ Selection("complete",
1180
+ nodes=("lahn_kalk", "lahn_leun"),
1181
+ elements=("land_dill_assl", "land_lahn_kalk",
1182
+ "land_lahn_leun", "land_lahn_marb",
1183
+ "stream_dill_assl_lahn_leun",
1184
+ "stream_lahn_leun_lahn_kalk",
1185
+ "stream_lahn_marb_lahn_leun"))
1186
+ """
1187
+ try:
1188
+ selection = Selection(name)
1189
+ for node in self.nodes:
1190
+ for substring in substrings:
1191
+ if substring in node.name:
1192
+ selection.nodes += node
1193
+ break
1194
+ except BaseException:
1195
+ values = objecttools.enumeration(substrings)
1196
+ objecttools.augment_excmessage(
1197
+ f"While trying to determine the nodes of selection `{self.name}` with "
1198
+ f"names containing at least one of the given substrings `{values}`"
1199
+ )
1200
+ return selection
1201
+
1202
+ def select_nodenames(self, *substrings: str) -> Selection:
1203
+ """Restrict the current selection to all nodes with a name containing at least
1204
+ one of the given substrings (does not affect any elements).
1205
+
1206
+ See the documentation on method |Selection.search_nodenames| for additional
1207
+ information.
1208
+ """
1209
+ self.nodes = self.search_nodenames(*substrings).nodes
1210
+ return self
1211
+
1212
+ def deselect_nodenames(self, *substrings: str) -> Selection:
1213
+ """Restrict the current selection to all nodes with a name not containing at
1214
+ least one of the given substrings (does not affect any elements).
1215
+
1216
+ See the documentation on method |Selection.search_nodenames| for additional
1217
+ information.
1218
+ """
1219
+ self.nodes -= self.search_nodenames(*substrings).nodes
1220
+ return self
1221
+
1222
+ def search_elementnames(
1223
+ self, *substrings: str, name: str = "elementnames"
1224
+ ) -> Selection:
1225
+ """Return a new selection containing all elements of the current selection with
1226
+ a name containing at least one of the given substrings.
1227
+
1228
+ >>> from hydpy.core.testtools import prepare_full_example_2
1229
+ >>> hp, pub, _ = prepare_full_example_2()
1230
+
1231
+ Pass the (sub)strings as positional arguments and, optionally, the name of the
1232
+ newly created |Selection| object as a keyword argument:
1233
+
1234
+ >>> test = pub.selections.complete.copy("test")
1235
+ >>> from hydpy import prepare_model
1236
+ >>> test.search_elementnames("dill", "lahn_marb")
1237
+ Selection("elementnames",
1238
+ nodes=(),
1239
+ elements=("land_dill_assl", "land_lahn_marb",
1240
+ "stream_dill_assl_lahn_leun",
1241
+ "stream_lahn_marb_lahn_leun"))
1242
+
1243
+ Wrong string specifications result in errors like the following:
1244
+
1245
+ >>> test.search_elementnames(["dill", "lahn_marb"])
1246
+ Traceback (most recent call last):
1247
+ ...
1248
+ TypeError: While trying to determine the elements of selection `test` with \
1249
+ names containing at least one of the given substrings `['dill', 'lahn_marb']`, the \
1250
+ following error occurred: 'in <string>' requires string as left operand, not list
1251
+
1252
+ Method |Selection.select_elementnames| restricts the current selection to the
1253
+ one determined with the method |Selection.search_elementnames|:
1254
+
1255
+ >>> test.select_elementnames("dill", "lahn_marb")
1256
+ Selection("test",
1257
+ nodes=("dill_assl", "lahn_kalk", "lahn_leun", "lahn_marb"),
1258
+ elements=("land_dill_assl", "land_lahn_marb",
1259
+ "stream_dill_assl_lahn_leun",
1260
+ "stream_lahn_marb_lahn_leun"))
1261
+
1262
+ On the contrary, the method |Selection.deselect_elementnames| restricts the
1263
+ current selection to all devices not determined by the method
1264
+ |Selection.search_elementnames|:
1265
+
1266
+ >>> pub.selections.complete.deselect_elementnames("dill", "lahn_marb")
1267
+ Selection("complete",
1268
+ nodes=("dill_assl", "lahn_kalk", "lahn_leun", "lahn_marb"),
1269
+ elements=("land_lahn_kalk", "land_lahn_leun",
1270
+ "stream_lahn_leun_lahn_kalk"))
1271
+ """
1272
+ try:
1273
+ selection = Selection(name)
1274
+ for element in self.elements:
1275
+ for substring in substrings:
1276
+ if substring in element.name:
1277
+ selection.elements += element
1278
+ break
1279
+ except BaseException:
1280
+ values = objecttools.enumeration(substrings)
1281
+ objecttools.augment_excmessage(
1282
+ f"While trying to determine the elements of selection `{self.name}` "
1283
+ f"with names containing at least one of the given substrings `{values}`"
1284
+ )
1285
+ return selection
1286
+
1287
+ def select_elementnames(self, *substrings: str) -> Selection:
1288
+ """Restrict the current selection to all elements with a name containing at
1289
+ least one of the given substrings (does not affect any nodes).
1290
+
1291
+ See the documentation on method |Selection.search_elementnames| for additional
1292
+ information.
1293
+ """
1294
+ self.elements = self.search_elementnames(*substrings).elements
1295
+ return self
1296
+
1297
+ def deselect_elementnames(self, *substrings: str) -> Selection:
1298
+ """Restrict the current selection to all elements with a name not containing at
1299
+ least one of the given substrings. (does not affect any nodes).
1300
+
1301
+ See the documentation on method |Selection.search_elementnames| for additional
1302
+ information.
1303
+ """
1304
+ self.elements -= self.search_elementnames(*substrings).elements
1305
+ return self
1306
+
1307
+ def copy(self, name: str) -> Selection:
1308
+ """Return a new |Selection| object with the given name and copies of the
1309
+ handled |Nodes| and |Elements| objects based on method |Devices.copy|."""
1310
+ return type(self)(name, copy.copy(self.nodes), copy.copy(self.elements))
1311
+
1312
+ def add_remotes(self) -> None:
1313
+ """Add all remote nodes linked to at least one of the currently handled
1314
+ elements.
1315
+
1316
+ One often encounters the situation (for example, after calling method
1317
+ |Selection.select_upstream|), when a selection does not explicitly include all
1318
+ relevant remote nodes, like in the following example:
1319
+
1320
+ >>> from hydpy import Element, Selection
1321
+ >>> dam = Element("dam", inlets="inflow", outlets="outflow",
1322
+ ... receivers="discharge_downstream", senders="water_level")
1323
+ >>> sel = Selection("Dam", elements=dam, nodes=("inflow", "outflow"))
1324
+ >>> sel
1325
+ Selection("Dam",
1326
+ nodes=("inflow", "outflow"),
1327
+ elements="dam")
1328
+
1329
+ The method |Selection.add_remotes| is a small auxiliary function that takes
1330
+ care of this:
1331
+
1332
+ >>> sel.add_remotes()
1333
+ >>> sel
1334
+ Selection("Dam",
1335
+ nodes=("discharge_downstream", "inflow", "outflow",
1336
+ "water_level"),
1337
+ elements="dam")
1338
+ """
1339
+ nodes = self.nodes
1340
+ for element in self.elements:
1341
+ for node in itertools.chain(element.receivers, element.senders):
1342
+ nodes.add_device(node)
1343
+
1344
+ def save_networkfile(
1345
+ self, filepath: str | None = None, write_defaultnodes: bool = True
1346
+ ) -> None:
1347
+ """Save the selection as a network file.
1348
+
1349
+ >>> from hydpy.core.testtools import prepare_full_example_2
1350
+ >>> _, pub, TestIO = prepare_full_example_2()
1351
+
1352
+ In most cases, one should conveniently write network files via method
1353
+ |NetworkManager.save_files| of class |NetworkManager|. However, using the
1354
+ method |Selection.save_networkfile| allows for additional configuration via the
1355
+ arguments `filepath` and `write_defaultnodes`:
1356
+
1357
+ >>> with TestIO():
1358
+ ... pub.selections.headwaters.save_networkfile()
1359
+ ... with open("headwaters.py") as networkfile:
1360
+ ... print(networkfile.read())
1361
+ from hydpy import Element, Node
1362
+ <BLANKLINE>
1363
+ <BLANKLINE>
1364
+ Node("dill_assl", variable="Q",
1365
+ keywords="gauge")
1366
+ <BLANKLINE>
1367
+ Node("lahn_marb", variable="Q",
1368
+ keywords="gauge")
1369
+ <BLANKLINE>
1370
+ <BLANKLINE>
1371
+ Element("land_dill_assl",
1372
+ outlets="dill_assl",
1373
+ keywords="catchment")
1374
+ <BLANKLINE>
1375
+ Element("land_lahn_marb",
1376
+ outlets="lahn_marb",
1377
+ keywords="catchment")
1378
+ <BLANKLINE>
1379
+
1380
+ >>> with TestIO():
1381
+ ... pub.selections.headwaters.save_networkfile(
1382
+ ... "test.py", write_defaultnodes=False)
1383
+ ... with open("test.py") as networkfile:
1384
+ ... print(networkfile.read())
1385
+ from hydpy import Element, Node
1386
+ <BLANKLINE>
1387
+ <BLANKLINE>
1388
+ Element("land_dill_assl",
1389
+ outlets="dill_assl",
1390
+ keywords="catchment")
1391
+ <BLANKLINE>
1392
+ Element("land_lahn_marb",
1393
+ outlets="lahn_marb",
1394
+ keywords="catchment")
1395
+ <BLANKLINE>
1396
+
1397
+ The `write_defaultnodes` argument does only affect nodes handling the default
1398
+ variable `Q`:
1399
+
1400
+ >>> from hydpy import FusedVariable, Node
1401
+ >>> from hydpy.aliases import (
1402
+ ... hland_inputs_P, hland_inputs_T, lland_inputs_Nied, dam_receivers_OWL,
1403
+ ... hland_fluxes_Perc, hland_fluxes_Q0, hland_fluxes_Q1,
1404
+ ... dam_factors_WaterLevel)
1405
+ >>> Precip = FusedVariable("Precip", hland_inputs_P, lland_inputs_Nied)
1406
+ >>> Runoff = FusedVariable("Runoff", hland_fluxes_Q0, hland_fluxes_Q1)
1407
+ >>> Level = FusedVariable("Level", dam_receivers_OWL, dam_factors_WaterLevel)
1408
+ >>> nodes = pub.selections.headwaters.nodes
1409
+ >>> nodes.add_device(Node("test1", variable="X"))
1410
+ >>> nodes.add_device(Node("test2", variable=hland_inputs_T))
1411
+ >>> nodes.add_device(Node("test3", variable=Precip))
1412
+ >>> nodes.add_device(Node("test4", variable=hland_fluxes_Perc))
1413
+ >>> nodes.add_device(Node("test5", variable=Runoff))
1414
+ >>> nodes.add_device(Node("test6", variable=Level))
1415
+ >>> with TestIO():
1416
+ ... pub.selections.headwaters.save_networkfile(
1417
+ ... "test.py", write_defaultnodes=False)
1418
+ ... with open("test.py") as networkfile:
1419
+ ... print(networkfile.read())
1420
+ from hydpy import Element, FusedVariable, Node
1421
+ from hydpy.aliases import (
1422
+ dam_factors_WaterLevel,
1423
+ dam_receivers_OWL,
1424
+ hland_fluxes_Perc,
1425
+ hland_fluxes_Q0,
1426
+ hland_fluxes_Q1,
1427
+ hland_inputs_P,
1428
+ hland_inputs_T,
1429
+ lland_inputs_Nied,
1430
+ )
1431
+ <BLANKLINE>
1432
+ <BLANKLINE>
1433
+ Level = FusedVariable("Level", dam_factors_WaterLevel, dam_receivers_OWL)
1434
+ Precip = FusedVariable("Precip", hland_inputs_P, lland_inputs_Nied)
1435
+ Runoff = FusedVariable("Runoff", hland_fluxes_Q0, hland_fluxes_Q1)
1436
+ <BLANKLINE>
1437
+ <BLANKLINE>
1438
+ Node("test1", variable="X")
1439
+ <BLANKLINE>
1440
+ Node("test2", variable=hland_inputs_T)
1441
+ <BLANKLINE>
1442
+ Node("test3", variable=Precip)
1443
+ <BLANKLINE>
1444
+ Node("test4", variable=hland_fluxes_Perc)
1445
+ <BLANKLINE>
1446
+ Node("test5", variable=Runoff)
1447
+ <BLANKLINE>
1448
+ Node("test6", variable=Level)
1449
+ <BLANKLINE>
1450
+ <BLANKLINE>
1451
+ Element("land_dill_assl",
1452
+ outlets="dill_assl",
1453
+ keywords="catchment")
1454
+ <BLANKLINE>
1455
+ Element("land_lahn_marb",
1456
+ outlets="lahn_marb",
1457
+ keywords="catchment")
1458
+ <BLANKLINE>
1459
+ """
1460
+ aliases: set[str] = set()
1461
+ fusedvariables: set[devicetools.FusedVariable] = set()
1462
+ for variable in self.nodes.variables:
1463
+ if isinstance(variable, str):
1464
+ continue
1465
+ if isinstance(variable, devicetools.FusedVariable):
1466
+ fusedvariables.add(variable)
1467
+ else:
1468
+ aliases.add(hydpy.sequence2alias[variable])
1469
+ for fusedvariable in fusedvariables:
1470
+ for sequence in fusedvariable:
1471
+ aliases.add(hydpy.sequence2alias[sequence])
1472
+ if filepath is None:
1473
+ filepath = self.name + ".py"
1474
+ with open(filepath, "w", encoding="utf-8") as file_:
1475
+ if fusedvariables:
1476
+ file_.write("from hydpy import Element, FusedVariable, Node")
1477
+ else:
1478
+ file_.write("from hydpy import Element, Node")
1479
+ if aliases:
1480
+ import_aliases = ", ".join(sorted(aliases))
1481
+ import_aliases = f"from hydpy.aliases import {import_aliases}"
1482
+ import_aliases = black.format_str(import_aliases, mode=black.FileMode())
1483
+ file_.write(f"\n{import_aliases}")
1484
+ file_.write("\n\n")
1485
+ for fusedvariable in sorted(fusedvariables, key=str):
1486
+ file_.write(f"{fusedvariable} = {repr(fusedvariable)}\n")
1487
+ if fusedvariables:
1488
+ file_.write("\n")
1489
+ written = False
1490
+ for node in self.nodes:
1491
+ if write_defaultnodes or (node.variable != "Q"):
1492
+ file_.write("\n" + repr(node) + "\n")
1493
+ written = True
1494
+ if written:
1495
+ file_.write("\n")
1496
+ for element in self.elements:
1497
+ file_.write("\n" + repr(element) + "\n")
1498
+
1499
+ def __len__(self) -> int:
1500
+ return len(self.nodes) + len(self.elements)
1501
+
1502
+ _ERRORMESSAGE = (
1503
+ "selection `{self.name}` with object `{other}` of type `{classname(other)}`"
1504
+ )
1505
+
1506
+ @objecttools.excmessage_decorator(f"add {_ERRORMESSAGE}")
1507
+ def __iadd__(self, other: Selection) -> Selection:
1508
+ self.nodes += other.nodes
1509
+ self.elements += other.elements
1510
+ return self
1511
+
1512
+ @objecttools.excmessage_decorator(f"subtract {_ERRORMESSAGE}")
1513
+ def __isub__(self, other: Selection) -> Selection:
1514
+ self.nodes -= other.nodes
1515
+ self.elements -= other.elements
1516
+ return self
1517
+
1518
+ @objecttools.excmessage_decorator(f"compare {_ERRORMESSAGE}")
1519
+ def __lt__(self, other: Selection) -> bool: # type: ignore[has-type]
1520
+ return (self.nodes < other.nodes) and (self.elements < other.elements)
1521
+
1522
+ @objecttools.excmessage_decorator(f"compare {_ERRORMESSAGE}")
1523
+ def __le__(self, other: Selection) -> bool: # type: ignore[has-type]
1524
+ return (self.nodes <= other.nodes) and (self.elements <= other.elements)
1525
+
1526
+ def __eq__(self, other: object) -> bool:
1527
+ if isinstance(other, (hydpytools.HydPy, Selection)):
1528
+ return (self.nodes == other.nodes) and (self.elements == other.elements)
1529
+ return False
1530
+
1531
+ def __ne__(self, other: object) -> bool:
1532
+ if isinstance(other, (hydpytools.HydPy, Selection)):
1533
+ return (self.nodes != other.nodes) or (self.elements != other.elements)
1534
+ return True
1535
+
1536
+ @objecttools.excmessage_decorator(f"compare {_ERRORMESSAGE}")
1537
+ def __ge__(self, other: Selection) -> bool:
1538
+ return (self.nodes >= other.nodes) and (self.elements >= other.elements)
1539
+
1540
+ @objecttools.excmessage_decorator(f"compare {_ERRORMESSAGE}")
1541
+ def __gt__(self, other: Selection) -> bool:
1542
+ return (self.nodes > other.nodes) and (self.elements >= other.elements)
1543
+
1544
+ def __hash__(self) -> int:
1545
+ return id(self)
1546
+
1547
+ def __str__(self) -> str:
1548
+ return self.name
1549
+
1550
+ def __repr__(self) -> str:
1551
+ return self.assignrepr("")
1552
+
1553
+ def assignrepr(self, prefix: str = "") -> str:
1554
+ """Return a |repr| string with a prefixed assignment."""
1555
+ with objecttools.repr_.preserve_strings(True):
1556
+ options = hydpy.pub.options
1557
+ with options.ellipsis(2, optional=True):
1558
+ with objecttools.assignrepr_tuple.always_bracketed(False):
1559
+ classname = type(self).__name__
1560
+ blanks = " " * (len(prefix + classname) + 1)
1561
+ nodestr = objecttools.assignrepr_tuple(
1562
+ self.nodes.names, blanks + "nodes=", 70
1563
+ )
1564
+ elementstr = objecttools.assignrepr_tuple(
1565
+ self.elements.names, blanks + "elements=", 70
1566
+ )
1567
+ return (
1568
+ f'{prefix}{classname}("{self.name}",\n'
1569
+ f"{nodestr},\n"
1570
+ f"{elementstr})"
1571
+ )