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.
- hydpy/__init__.py +275 -0
- hydpy/aliases.py +2554 -0
- hydpy/auxs/__init__.py +0 -0
- hydpy/auxs/anntools.py +1305 -0
- hydpy/auxs/armatools.py +883 -0
- hydpy/auxs/calibtools.py +3337 -0
- hydpy/auxs/interptools.py +1094 -0
- hydpy/auxs/iuhtools.py +543 -0
- hydpy/auxs/networktools.py +597 -0
- hydpy/auxs/ppolytools.py +809 -0
- hydpy/auxs/quadtools.py +61 -0
- hydpy/auxs/roottools.py +228 -0
- hydpy/auxs/smoothtools.py +273 -0
- hydpy/auxs/statstools.py +2125 -0
- hydpy/auxs/validtools.py +81 -0
- hydpy/conf/HydPyConfigBase.xsd +68637 -0
- hydpy/conf/HydPyConfigBase.xsdt +358 -0
- hydpy/conf/HydPyConfigMultipleRuns.xsd +25 -0
- hydpy/conf/HydPyConfigSingleRun.xsd +24 -0
- hydpy/conf/__init__.py +0 -0
- hydpy/conf/a_coefficients_explicit_lobatto_sequence.npy +0 -0
- hydpy/conf/support_points_for_smoothpar_logistic2.npy +0 -0
- hydpy/config.py +42 -0
- hydpy/core/__init__.py +0 -0
- hydpy/core/aliastools.py +214 -0
- hydpy/core/autodoctools.py +1947 -0
- hydpy/core/auxfiletools.py +1169 -0
- hydpy/core/devicetools.py +3810 -0
- hydpy/core/exceptiontools.py +269 -0
- hydpy/core/filetools.py +1985 -0
- hydpy/core/hydpytools.py +3089 -0
- hydpy/core/importtools.py +1398 -0
- hydpy/core/indextools.py +345 -0
- hydpy/core/itemtools.py +1849 -0
- hydpy/core/masktools.py +460 -0
- hydpy/core/modeltools.py +4868 -0
- hydpy/core/netcdftools.py +2683 -0
- hydpy/core/objecttools.py +2023 -0
- hydpy/core/optiontools.py +1045 -0
- hydpy/core/parametertools.py +4674 -0
- hydpy/core/printtools.py +222 -0
- hydpy/core/propertytools.py +643 -0
- hydpy/core/pubtools.py +254 -0
- hydpy/core/selectiontools.py +1571 -0
- hydpy/core/sequencetools.py +4476 -0
- hydpy/core/seriestools.py +339 -0
- hydpy/core/testtools.py +2483 -0
- hydpy/core/timetools.py +3567 -0
- hydpy/core/typingtools.py +333 -0
- hydpy/core/variabletools.py +2615 -0
- hydpy/cythons/__init__.py +24 -0
- hydpy/cythons/annutils.pxd +33 -0
- hydpy/cythons/annutils.pyi +25 -0
- hydpy/cythons/annutils.pyx +120 -0
- hydpy/cythons/autogen/__init__.py +0 -0
- hydpy/cythons/autogen/annutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/annutils.pxd +42 -0
- hydpy/cythons/autogen/annutils.pyx +129 -0
- hydpy/cythons/autogen/c_arma.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_arma.pxd +179 -0
- hydpy/cythons/autogen/c_arma.pyx +356 -0
- hydpy/cythons/autogen/c_arma_rimorido.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_arma_rimorido.pxd +179 -0
- hydpy/cythons/autogen/c_arma_rimorido.pyx +356 -0
- hydpy/cythons/autogen/c_conv.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_conv.pxd +198 -0
- hydpy/cythons/autogen/c_conv.pyx +491 -0
- hydpy/cythons/autogen/c_conv_idw.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_conv_idw.pxd +124 -0
- hydpy/cythons/autogen/c_conv_idw.pyx +264 -0
- hydpy/cythons/autogen/c_conv_idw_ed.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_conv_idw_ed.pxd +197 -0
- hydpy/cythons/autogen/c_conv_idw_ed.pyx +481 -0
- hydpy/cythons/autogen/c_conv_nn.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_conv_nn.pxd +120 -0
- hydpy/cythons/autogen/c_conv_nn.pyx +224 -0
- hydpy/cythons/autogen/c_dam.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam.pxd +805 -0
- hydpy/cythons/autogen/c_dam.pyx +1477 -0
- hydpy/cythons/autogen/c_dam_llake.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_llake.pxd +364 -0
- hydpy/cythons/autogen/c_dam_llake.pyx +705 -0
- hydpy/cythons/autogen/c_dam_lreservoir.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_lreservoir.pxd +365 -0
- hydpy/cythons/autogen/c_dam_lreservoir.pyx +708 -0
- hydpy/cythons/autogen/c_dam_lretention.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_lretention.pxd +340 -0
- hydpy/cythons/autogen/c_dam_lretention.pyx +625 -0
- hydpy/cythons/autogen/c_dam_pump.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_pump.pxd +402 -0
- hydpy/cythons/autogen/c_dam_pump.pyx +724 -0
- hydpy/cythons/autogen/c_dam_pump_sluice.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_pump_sluice.pxd +452 -0
- hydpy/cythons/autogen/c_dam_pump_sluice.pyx +829 -0
- hydpy/cythons/autogen/c_dam_sluice.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_sluice.pxd +404 -0
- hydpy/cythons/autogen/c_dam_sluice.pyx +726 -0
- hydpy/cythons/autogen/c_dam_v001.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v001.pxd +452 -0
- hydpy/cythons/autogen/c_dam_v001.pyx +816 -0
- hydpy/cythons/autogen/c_dam_v002.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v002.pxd +394 -0
- hydpy/cythons/autogen/c_dam_v002.pyx +703 -0
- hydpy/cythons/autogen/c_dam_v003.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v003.pxd +417 -0
- hydpy/cythons/autogen/c_dam_v003.pyx +744 -0
- hydpy/cythons/autogen/c_dam_v004.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v004.pxd +486 -0
- hydpy/cythons/autogen/c_dam_v004.pyx +891 -0
- hydpy/cythons/autogen/c_dam_v005.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dam_v005.pxd +524 -0
- hydpy/cythons/autogen/c_dam_v005.pyx +928 -0
- hydpy/cythons/autogen/c_dummy.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy.pxd +151 -0
- hydpy/cythons/autogen/c_dummy.pyx +263 -0
- hydpy/cythons/autogen/c_dummy_interceptedwater.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_interceptedwater.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_interceptedwater.pyx +104 -0
- hydpy/cythons/autogen/c_dummy_node2node.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_node2node.pxd +89 -0
- hydpy/cythons/autogen/c_dummy_node2node.pyx +148 -0
- hydpy/cythons/autogen/c_dummy_snowalbedo.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_snowalbedo.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_snowalbedo.pyx +104 -0
- hydpy/cythons/autogen/c_dummy_snowcover.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_snowcover.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_snowcover.pyx +104 -0
- hydpy/cythons/autogen/c_dummy_snowycanopy.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_snowycanopy.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_snowycanopy.pyx +104 -0
- hydpy/cythons/autogen/c_dummy_soilwater.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_dummy_soilwater.pxd +69 -0
- hydpy/cythons/autogen/c_dummy_soilwater.pyx +104 -0
- hydpy/cythons/autogen/c_evap.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap.pxd +1029 -0
- hydpy/cythons/autogen/c_evap.pyx +2601 -0
- hydpy/cythons/autogen/c_evap_aet_hbv96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_aet_hbv96.pxd +227 -0
- hydpy/cythons/autogen/c_evap_aet_hbv96.pyx +584 -0
- hydpy/cythons/autogen/c_evap_aet_minhas.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_aet_minhas.pxd +193 -0
- hydpy/cythons/autogen/c_evap_aet_minhas.pyx +478 -0
- hydpy/cythons/autogen/c_evap_aet_morsim.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_aet_morsim.pxd +681 -0
- hydpy/cythons/autogen/c_evap_aet_morsim.pyx +1642 -0
- hydpy/cythons/autogen/c_evap_pet_ambav1.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_pet_ambav1.pxd +532 -0
- hydpy/cythons/autogen/c_evap_pet_ambav1.pyx +1296 -0
- hydpy/cythons/autogen/c_evap_pet_hbv96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_pet_hbv96.pxd +179 -0
- hydpy/cythons/autogen/c_evap_pet_hbv96.pyx +328 -0
- hydpy/cythons/autogen/c_evap_pet_m.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_pet_m.pxd +124 -0
- hydpy/cythons/autogen/c_evap_pet_m.pyx +214 -0
- hydpy/cythons/autogen/c_evap_pet_mlc.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_pet_mlc.pxd +126 -0
- hydpy/cythons/autogen/c_evap_pet_mlc.pyx +214 -0
- hydpy/cythons/autogen/c_evap_ret_fao56.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_ret_fao56.pxd +305 -0
- hydpy/cythons/autogen/c_evap_ret_fao56.pyx +624 -0
- hydpy/cythons/autogen/c_evap_ret_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_ret_io.pxd +112 -0
- hydpy/cythons/autogen/c_evap_ret_io.pyx +176 -0
- hydpy/cythons/autogen/c_evap_ret_tw2002.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_evap_ret_tw2002.pxd +139 -0
- hydpy/cythons/autogen/c_evap_ret_tw2002.pyx +273 -0
- hydpy/cythons/autogen/c_exch.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_exch.pxd +230 -0
- hydpy/cythons/autogen/c_exch.pyx +462 -0
- hydpy/cythons/autogen/c_exch_branch_hbv96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_exch_branch_hbv96.pxd +134 -0
- hydpy/cythons/autogen/c_exch_branch_hbv96.pyx +255 -0
- hydpy/cythons/autogen/c_exch_waterlevel.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_exch_waterlevel.pxd +54 -0
- hydpy/cythons/autogen/c_exch_waterlevel.pyx +78 -0
- hydpy/cythons/autogen/c_exch_weir_hbv96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_exch_weir_hbv96.pxd +156 -0
- hydpy/cythons/autogen/c_exch_weir_hbv96.pyx +282 -0
- hydpy/cythons/autogen/c_ga.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_ga.pxd +353 -0
- hydpy/cythons/autogen/c_ga.pyx +1204 -0
- hydpy/cythons/autogen/c_ga_garto.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_ga_garto.pxd +330 -0
- hydpy/cythons/autogen/c_ga_garto.pyx +1105 -0
- hydpy/cythons/autogen/c_ga_garto_submodel1.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_ga_garto_submodel1.pxd +236 -0
- hydpy/cythons/autogen/c_ga_garto_submodel1.pyx +944 -0
- hydpy/cythons/autogen/c_gland.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_gland.pxd +437 -0
- hydpy/cythons/autogen/c_gland.pyx +726 -0
- hydpy/cythons/autogen/c_gland_gr4.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_gland_gr4.pxd +382 -0
- hydpy/cythons/autogen/c_gland_gr4.pyx +605 -0
- hydpy/cythons/autogen/c_gland_gr5.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_gland_gr5.pxd +368 -0
- hydpy/cythons/autogen/c_gland_gr5.pyx +568 -0
- hydpy/cythons/autogen/c_gland_gr6.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_gland_gr6.pxd +420 -0
- hydpy/cythons/autogen/c_gland_gr6.pyx +673 -0
- hydpy/cythons/autogen/c_hland.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_hland.pxd +855 -0
- hydpy/cythons/autogen/c_hland.pyx +2486 -0
- hydpy/cythons/autogen/c_hland_96.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_hland_96.pxd +631 -0
- hydpy/cythons/autogen/c_hland_96.pyx +1724 -0
- hydpy/cythons/autogen/c_hland_96c.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_hland_96c.pxd +621 -0
- hydpy/cythons/autogen/c_hland_96c.pyx +1822 -0
- hydpy/cythons/autogen/c_hland_96p.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_hland_96p.pxd +683 -0
- hydpy/cythons/autogen/c_hland_96p.pyx +1911 -0
- hydpy/cythons/autogen/c_kinw.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_kinw.pxd +509 -0
- hydpy/cythons/autogen/c_kinw.pyx +965 -0
- hydpy/cythons/autogen/c_kinw_williams.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_kinw_williams.pxd +409 -0
- hydpy/cythons/autogen/c_kinw_williams.pyx +763 -0
- hydpy/cythons/autogen/c_kinw_williams_ext.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_kinw_williams_ext.pxd +220 -0
- hydpy/cythons/autogen/c_kinw_williams_ext.pyx +440 -0
- hydpy/cythons/autogen/c_lland.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_lland.pxd +1386 -0
- hydpy/cythons/autogen/c_lland.pyx +3679 -0
- hydpy/cythons/autogen/c_lland_dd.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_lland_dd.pxd +679 -0
- hydpy/cythons/autogen/c_lland_dd.pyx +1719 -0
- hydpy/cythons/autogen/c_lland_knauf.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_lland_knauf.pxd +1096 -0
- hydpy/cythons/autogen/c_lland_knauf.pyx +2784 -0
- hydpy/cythons/autogen/c_lland_knauf_ic.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_lland_knauf_ic.pxd +1369 -0
- hydpy/cythons/autogen/c_lland_knauf_ic.pyx +3625 -0
- hydpy/cythons/autogen/c_meteo.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo.pxd +469 -0
- hydpy/cythons/autogen/c_meteo.pyx +879 -0
- hydpy/cythons/autogen/c_meteo_clear_glob_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_clear_glob_io.pxd +75 -0
- hydpy/cythons/autogen/c_meteo_clear_glob_io.pyx +107 -0
- hydpy/cythons/autogen/c_meteo_glob_fao56.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_glob_fao56.pxd +209 -0
- hydpy/cythons/autogen/c_meteo_glob_fao56.pyx +339 -0
- hydpy/cythons/autogen/c_meteo_glob_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_glob_io.pxd +63 -0
- hydpy/cythons/autogen/c_meteo_glob_io.pyx +91 -0
- hydpy/cythons/autogen/c_meteo_glob_morsim.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_glob_morsim.pxd +289 -0
- hydpy/cythons/autogen/c_meteo_glob_morsim.pyx +527 -0
- hydpy/cythons/autogen/c_meteo_precip_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_precip_io.pxd +112 -0
- hydpy/cythons/autogen/c_meteo_precip_io.pyx +176 -0
- hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.pxd +87 -0
- hydpy/cythons/autogen/c_meteo_psun_sun_glob_io.pyx +123 -0
- hydpy/cythons/autogen/c_meteo_sun_fao56.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_sun_fao56.pxd +209 -0
- hydpy/cythons/autogen/c_meteo_sun_fao56.pyx +343 -0
- hydpy/cythons/autogen/c_meteo_sun_morsim.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_sun_morsim.pxd +286 -0
- hydpy/cythons/autogen/c_meteo_sun_morsim.pyx +519 -0
- hydpy/cythons/autogen/c_meteo_temp_io.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_meteo_temp_io.pxd +112 -0
- hydpy/cythons/autogen/c_meteo_temp_io.pyx +176 -0
- hydpy/cythons/autogen/c_musk.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_musk.pxd +282 -0
- hydpy/cythons/autogen/c_musk.pyx +605 -0
- hydpy/cythons/autogen/c_musk_classic.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_musk_classic.pxd +138 -0
- hydpy/cythons/autogen/c_musk_classic.pyx +226 -0
- hydpy/cythons/autogen/c_musk_mct.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_musk_mct.pxd +282 -0
- hydpy/cythons/autogen/c_musk_mct.pyx +609 -0
- hydpy/cythons/autogen/c_rconc.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_rconc.pxd +119 -0
- hydpy/cythons/autogen/c_rconc.pyx +174 -0
- hydpy/cythons/autogen/c_rconc_nash.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_rconc_nash.pxd +111 -0
- hydpy/cythons/autogen/c_rconc_nash.pyx +185 -0
- hydpy/cythons/autogen/c_rconc_uh.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_rconc_uh.pxd +92 -0
- hydpy/cythons/autogen/c_rconc_uh.pyx +125 -0
- hydpy/cythons/autogen/c_sw1d.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d.pxd +511 -0
- hydpy/cythons/autogen/c_sw1d.pyx +1263 -0
- hydpy/cythons/autogen/c_sw1d_channel.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_channel.pxd +119 -0
- hydpy/cythons/autogen/c_sw1d_channel.pyx +300 -0
- hydpy/cythons/autogen/c_sw1d_gate_out.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_gate_out.pxd +240 -0
- hydpy/cythons/autogen/c_sw1d_gate_out.pyx +476 -0
- hydpy/cythons/autogen/c_sw1d_lias.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_lias.pxd +320 -0
- hydpy/cythons/autogen/c_sw1d_lias.pyx +619 -0
- hydpy/cythons/autogen/c_sw1d_lias_sluice.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_lias_sluice.pxd +325 -0
- hydpy/cythons/autogen/c_sw1d_lias_sluice.pyx +644 -0
- hydpy/cythons/autogen/c_sw1d_network.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_network.pxd +90 -0
- hydpy/cythons/autogen/c_sw1d_network.pyx +246 -0
- hydpy/cythons/autogen/c_sw1d_pump.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_pump.pxd +256 -0
- hydpy/cythons/autogen/c_sw1d_pump.pyx +502 -0
- hydpy/cythons/autogen/c_sw1d_q_in.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_q_in.pxd +224 -0
- hydpy/cythons/autogen/c_sw1d_q_in.pyx +383 -0
- hydpy/cythons/autogen/c_sw1d_q_out.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_q_out.pxd +224 -0
- hydpy/cythons/autogen/c_sw1d_q_out.pyx +383 -0
- hydpy/cythons/autogen/c_sw1d_storage.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_storage.pxd +193 -0
- hydpy/cythons/autogen/c_sw1d_storage.pyx +349 -0
- hydpy/cythons/autogen/c_sw1d_weir_out.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_sw1d_weir_out.pxd +212 -0
- hydpy/cythons/autogen/c_sw1d_weir_out.pyx +404 -0
- hydpy/cythons/autogen/c_test.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_test.pxd +175 -0
- hydpy/cythons/autogen/c_test.pyx +348 -0
- hydpy/cythons/autogen/c_test_discontinous.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_test_discontinous.pxd +146 -0
- hydpy/cythons/autogen/c_test_discontinous.pyx +256 -0
- hydpy/cythons/autogen/c_test_stiff0d.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_test_stiff0d.pxd +146 -0
- hydpy/cythons/autogen/c_test_stiff0d.pyx +250 -0
- hydpy/cythons/autogen/c_test_stiff1d.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_test_stiff1d.pxd +145 -0
- hydpy/cythons/autogen/c_test_stiff1d.pyx +294 -0
- hydpy/cythons/autogen/c_whmod.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_whmod.pxd +482 -0
- hydpy/cythons/autogen/c_whmod.pyx +1156 -0
- hydpy/cythons/autogen/c_whmod_rural.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_whmod_rural.pxd +411 -0
- hydpy/cythons/autogen/c_whmod_rural.pyx +982 -0
- hydpy/cythons/autogen/c_whmod_urban.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_whmod_urban.pxd +482 -0
- hydpy/cythons/autogen/c_whmod_urban.pyx +1155 -0
- hydpy/cythons/autogen/c_wland.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wland.pxd +842 -0
- hydpy/cythons/autogen/c_wland.pyx +1890 -0
- hydpy/cythons/autogen/c_wland_gd.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wland_gd.pxd +829 -0
- hydpy/cythons/autogen/c_wland_gd.pyx +1847 -0
- hydpy/cythons/autogen/c_wland_wag.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wland_wag.pxd +810 -0
- hydpy/cythons/autogen/c_wland_wag.pyx +1780 -0
- hydpy/cythons/autogen/c_wq.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wq.pxd +275 -0
- hydpy/cythons/autogen/c_wq.pyx +652 -0
- hydpy/cythons/autogen/c_wq_trapeze.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wq_trapeze.pxd +170 -0
- hydpy/cythons/autogen/c_wq_trapeze.pyx +400 -0
- hydpy/cythons/autogen/c_wq_trapeze_strickler.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wq_trapeze_strickler.pxd +243 -0
- hydpy/cythons/autogen/c_wq_trapeze_strickler.pyx +578 -0
- hydpy/cythons/autogen/c_wq_walrus.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/c_wq_walrus.pxd +61 -0
- hydpy/cythons/autogen/c_wq_walrus.pyx +82 -0
- hydpy/cythons/autogen/configutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/configutils.pxd +17 -0
- hydpy/cythons/autogen/configutils.pyx +119 -0
- hydpy/cythons/autogen/interfaceutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/interfaceutils.pxd +31 -0
- hydpy/cythons/autogen/interfaceutils.pyx +82 -0
- hydpy/cythons/autogen/interputils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/interputils.pxd +42 -0
- hydpy/cythons/autogen/interputils.pyx +118 -0
- hydpy/cythons/autogen/masterinterface.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/masterinterface.pxd +153 -0
- hydpy/cythons/autogen/masterinterface.pyx +222 -0
- hydpy/cythons/autogen/pointerutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/pointerutils.pxd +31 -0
- hydpy/cythons/autogen/pointerutils.pyx +650 -0
- hydpy/cythons/autogen/ppolyutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/ppolyutils.pxd +35 -0
- hydpy/cythons/autogen/ppolyutils.pyx +59 -0
- hydpy/cythons/autogen/quadutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/quadutils.pxd +26 -0
- hydpy/cythons/autogen/quadutils.pyx +973 -0
- hydpy/cythons/autogen/rootutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/rootutils.pxd +28 -0
- hydpy/cythons/autogen/rootutils.pyx +109 -0
- hydpy/cythons/autogen/sequenceutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/sequenceutils.pxd +45 -0
- hydpy/cythons/autogen/sequenceutils.pyx +101 -0
- hydpy/cythons/autogen/smoothutils.cp313-win_amd64.pyd +0 -0
- hydpy/cythons/autogen/smoothutils.pxd +29 -0
- hydpy/cythons/autogen/smoothutils.pyx +833 -0
- hydpy/cythons/configutils.pxd +8 -0
- hydpy/cythons/configutils.pyi +5 -0
- hydpy/cythons/configutils.pyx +110 -0
- hydpy/cythons/interfaceutils.pxd +22 -0
- hydpy/cythons/interfaceutils.pyi +15 -0
- hydpy/cythons/interfaceutils.pyx +73 -0
- hydpy/cythons/interputils.pxd +33 -0
- hydpy/cythons/interputils.pyi +32 -0
- hydpy/cythons/interputils.pyx +109 -0
- hydpy/cythons/modelutils.py +2990 -0
- hydpy/cythons/pointerutils.pxd +22 -0
- hydpy/cythons/pointerutils.pyi +89 -0
- hydpy/cythons/pointerutils.pyx +641 -0
- hydpy/cythons/ppolyutils.pxd +26 -0
- hydpy/cythons/ppolyutils.pyi +21 -0
- hydpy/cythons/ppolyutils.pyx +50 -0
- hydpy/cythons/quadutils.pxd +17 -0
- hydpy/cythons/quadutils.pyi +13 -0
- hydpy/cythons/quadutils.pyx +964 -0
- hydpy/cythons/rootutils.pxd +19 -0
- hydpy/cythons/rootutils.pyi +21 -0
- hydpy/cythons/rootutils.pyx +100 -0
- hydpy/cythons/sequenceutils.pxd +36 -0
- hydpy/cythons/sequenceutils.pyi +7 -0
- hydpy/cythons/sequenceutils.pyx +92 -0
- hydpy/cythons/smoothutils.pxd +20 -0
- hydpy/cythons/smoothutils.pyi +15 -0
- hydpy/cythons/smoothutils.pyx +824 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_dill_assl.py +13 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_kalk.py +13 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_leun.py +14 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/land_lahn_marb.py +13 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_dill_assl_lahn_leun.py +5 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_lahn_leun_lahn_kalk.py +5 -0
- hydpy/data/HydPy-H-Lahn/conditions/init_1996_01_01_00_00_00/stream_lahn_marb_lahn_leun.py +5 -0
- hydpy/data/HydPy-H-Lahn/control/default/land.py +9 -0
- hydpy/data/HydPy-H-Lahn/control/default/land_dill_assl.py +57 -0
- hydpy/data/HydPy-H-Lahn/control/default/land_lahn_kalk.py +57 -0
- hydpy/data/HydPy-H-Lahn/control/default/land_lahn_leun.py +56 -0
- hydpy/data/HydPy-H-Lahn/control/default/land_lahn_marb.py +57 -0
- hydpy/data/HydPy-H-Lahn/control/default/stream_dill_assl_lahn_leun.py +7 -0
- hydpy/data/HydPy-H-Lahn/control/default/stream_lahn_leun_lahn_kalk.py +7 -0
- hydpy/data/HydPy-H-Lahn/control/default/stream_lahn_marb_lahn_leun.py +7 -0
- hydpy/data/HydPy-H-Lahn/multiple_runs.xml +309 -0
- hydpy/data/HydPy-H-Lahn/multiple_runs_alpha.xml +71 -0
- hydpy/data/HydPy-H-Lahn/network/default/headwaters.py +11 -0
- hydpy/data/HydPy-H-Lahn/network/default/nonheadwaters.py +11 -0
- hydpy/data/HydPy-H-Lahn/network/default/streams.py +8 -0
- hydpy/data/HydPy-H-Lahn/series/default/dill_assl_obs_q.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/evap_pet_hbv96_input_normalairtemperature.nc +0 -0
- hydpy/data/HydPy-H-Lahn/series/default/evap_pet_hbv96_input_normalevapotranspiration.nc +0 -0
- hydpy/data/HydPy-H-Lahn/series/default/hland_96_input_p.nc +0 -0
- hydpy/data/HydPy-H-Lahn/series/default/hland_96_input_t.nc +0 -0
- hydpy/data/HydPy-H-Lahn/series/default/lahn_kalk_obs_q.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/lahn_leun_obs_q.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/lahn_marb_obs_q.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_hland_96_input_p.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_dill_assl_hland_96_input_t.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_hland_96_input_p.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_kalk_hland_96_input_t.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_hland_96_input_p.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_leun_hland_96_input_t.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_evap_pet_hbv96_input_normalairtemperature.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_evap_pet_hbv96_input_normalevapotranspiration.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_hland_96_input_p.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/land_lahn_marb_hland_96_input_t.asc +11387 -0
- hydpy/data/HydPy-H-Lahn/series/default/obs_q.nc +0 -0
- hydpy/data/HydPy-H-Lahn/single_run.xml +152 -0
- hydpy/data/HydPy-H-Lahn/single_run.xmlt +143 -0
- hydpy/data/__init__.py +17 -0
- hydpy/docs/__init__.py +0 -0
- hydpy/docs/autofigs/__init__.py +0 -0
- hydpy/docs/bib/__init__.py +0 -0
- hydpy/docs/bib/refs.bib +566 -0
- hydpy/docs/combine_docversions.py +133 -0
- hydpy/docs/draw_model_sketches.py +1301 -0
- hydpy/docs/enable_autodoc.py +7 -0
- hydpy/docs/figs/HydPy-G-GR4.png +0 -0
- hydpy/docs/figs/HydPy-G-GR5.png +0 -0
- hydpy/docs/figs/HydPy-G-GR6.png +0 -0
- hydpy/docs/figs/HydPy-H-HBV96-COSERO.png +0 -0
- hydpy/docs/figs/HydPy-H-HBV96-PREVAH.png +0 -0
- hydpy/docs/figs/HydPy-H-HBV96.png +0 -0
- hydpy/docs/figs/HydPy-H-Lahn.png +0 -0
- hydpy/docs/figs/HydPy-KinW-Williams.png +0 -0
- hydpy/docs/figs/HydPy-L-DD.png +0 -0
- hydpy/docs/figs/HydPy-W-Wag.png +0 -0
- hydpy/docs/figs/HydPy_Logo.png +0 -0
- hydpy/docs/figs/HydPy_Logo_Text.png +0 -0
- hydpy/docs/figs/IDLE-editor.png +0 -0
- hydpy/docs/figs/IDLE-shell.png +0 -0
- hydpy/docs/figs/LAWA_river-basin-bumbers.png +0 -0
- hydpy/docs/figs/__init__.py +0 -0
- hydpy/docs/html_/__init__.py +0 -0
- hydpy/docs/polish_html.py +57 -0
- hydpy/docs/prepare.py +224 -0
- hydpy/docs/publish_docs.py +53 -0
- hydpy/docs/rst/HydPy-ARMA.rst +27 -0
- hydpy/docs/rst/HydPy-Conv.rst +22 -0
- hydpy/docs/rst/HydPy-Dam.rst +79 -0
- hydpy/docs/rst/HydPy-Dummy.rst +21 -0
- hydpy/docs/rst/HydPy-Evap.rst +26 -0
- hydpy/docs/rst/HydPy-Exch.rst +36 -0
- hydpy/docs/rst/HydPy-G.rst +40 -0
- hydpy/docs/rst/HydPy-GA.rst +34 -0
- hydpy/docs/rst/HydPy-H.rst +24 -0
- hydpy/docs/rst/HydPy-KinW.rst +32 -0
- hydpy/docs/rst/HydPy-L.rst +42 -0
- hydpy/docs/rst/HydPy-Meteo.rst +28 -0
- hydpy/docs/rst/HydPy-Musk.rst +21 -0
- hydpy/docs/rst/HydPy-Rconc.rst +17 -0
- hydpy/docs/rst/HydPy-SW1D.rst +49 -0
- hydpy/docs/rst/HydPy-Test.rst +19 -0
- hydpy/docs/rst/HydPy-W.rst +20 -0
- hydpy/docs/rst/HydPy-WHMod.rst +19 -0
- hydpy/docs/rst/HydPy-WQ.rst +20 -0
- hydpy/docs/rst/__init__.py +0 -0
- hydpy/docs/rst/additional_repositories.rst +40 -0
- hydpy/docs/rst/auxiliaries.rst +31 -0
- hydpy/docs/rst/continuous_integration.rst +75 -0
- hydpy/docs/rst/core.rst +75 -0
- hydpy/docs/rst/cythons.rst +47 -0
- hydpy/docs/rst/definitions.rst +506 -0
- hydpy/docs/rst/developer_guide.rst +54 -0
- hydpy/docs/rst/example_projects.rst +40 -0
- hydpy/docs/rst/execution.rst +22 -0
- hydpy/docs/rst/framework_tools.rst +56 -0
- hydpy/docs/rst/how_to_read_the_reference_manual.rst +156 -0
- hydpy/docs/rst/hydpydependencies.rst +55 -0
- hydpy/docs/rst/index.rst +125 -0
- hydpy/docs/rst/installation.rst +155 -0
- hydpy/docs/rst/model_families.rst +79 -0
- hydpy/docs/rst/model_overview.rst +291 -0
- hydpy/docs/rst/modelimports.rst +10 -0
- hydpy/docs/rst/options.rst +119 -0
- hydpy/docs/rst/programming_style.rst +572 -0
- hydpy/docs/rst/project_structure.rst +520 -0
- hydpy/docs/rst/quickstart.rst +304 -0
- hydpy/docs/rst/reference_manual.rst +29 -0
- hydpy/docs/rst/required_tools.rst +50 -0
- hydpy/docs/rst/simulation.rst +514 -0
- hydpy/docs/rst/submodel_interfaces.rst +32 -0
- hydpy/docs/rst/tests_and_documentation.rst +85 -0
- hydpy/docs/rst/user_guide.rst +38 -0
- hydpy/docs/rst/version_control.rst +116 -0
- hydpy/docs/rst/zbibliography.rst +8 -0
- hydpy/docs/sphinx/__init__.py +0 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/changes/frameset.html +11 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/changes/rstsource.html +15 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/changes/versionchanges.html +33 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/defindex.html +35 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/domainindex.html +56 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/genindex-single.html +63 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/genindex-split.html +41 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/genindex.html +76 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/globaltoc.html +11 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/layout.html +221 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/localtoc.html +15 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/opensearch.xml +13 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/page.html +13 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/relations.html +23 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/search.html +65 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/searchbox.html +21 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/searchfield.html +23 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/sourcelink.html +18 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/basic.css_t +925 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/doctools.js +156 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/documentation_options.js_t +13 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/file.png +0 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/language_data.js_t +26 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/minus.png +0 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/plus.png +0 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/searchtools.js +574 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/static/sphinx_highlight.js +154 -0
- hydpy/docs/sphinx/_themes/basic_hydpy/theme.conf +16 -0
- hydpy/docs/sphinx/_themes/classic_hydpy/layout.html +23 -0
- hydpy/docs/sphinx/_themes/classic_hydpy/static/classic.css_t +358 -0
- hydpy/docs/sphinx/_themes/classic_hydpy/static/sidebar.js_t +72 -0
- hydpy/docs/sphinx/_themes/classic_hydpy/theme.conf +32 -0
- hydpy/docs/sphinx/conf.py +398 -0
- hydpy/docs/sphinx/defaultlinks_extension.py +36 -0
- hydpy/docs/sphinx/integrationtest_extension.py +104 -0
- hydpy/docs/sphinx/projectstructure_extension.py +58 -0
- hydpy/docs/sphinx/submodelgraph_extension.py +53 -0
- hydpy/exe/__init__.py +0 -0
- hydpy/exe/commandtools.py +651 -0
- hydpy/exe/hyd.py +277 -0
- hydpy/exe/modelimports.py +41 -0
- hydpy/exe/replacetools.py +216 -0
- hydpy/exe/servertools.py +2348 -0
- hydpy/exe/xmltools.py +3280 -0
- hydpy/interfaces/__init__.py +0 -0
- hydpy/interfaces/aetinterfaces.py +94 -0
- hydpy/interfaces/dischargeinterfaces.py +45 -0
- hydpy/interfaces/petinterfaces.py +117 -0
- hydpy/interfaces/precipinterfaces.py +42 -0
- hydpy/interfaces/radiationinterfaces.py +79 -0
- hydpy/interfaces/rconcinterfaces.py +30 -0
- hydpy/interfaces/routinginterfaces.py +324 -0
- hydpy/interfaces/soilinterfaces.py +96 -0
- hydpy/interfaces/stateinterfaces.py +98 -0
- hydpy/interfaces/tempinterfaces.py +46 -0
- hydpy/models/__init__.py +0 -0
- hydpy/models/arma/__init__.py +14 -0
- hydpy/models/arma/arma_control.py +383 -0
- hydpy/models/arma/arma_derived.py +204 -0
- hydpy/models/arma/arma_fluxes.py +41 -0
- hydpy/models/arma/arma_inlets.py +11 -0
- hydpy/models/arma/arma_logs.py +19 -0
- hydpy/models/arma/arma_model.py +461 -0
- hydpy/models/arma/arma_outlets.py +11 -0
- hydpy/models/arma_rimorido.py +381 -0
- hydpy/models/conv/__init__.py +12 -0
- hydpy/models/conv/conv_control.py +303 -0
- hydpy/models/conv/conv_derived.py +271 -0
- hydpy/models/conv/conv_fluxes.py +54 -0
- hydpy/models/conv/conv_inlets.py +11 -0
- hydpy/models/conv/conv_model.py +687 -0
- hydpy/models/conv/conv_outlets.py +11 -0
- hydpy/models/conv_idw.py +120 -0
- hydpy/models/conv_idw_ed.py +184 -0
- hydpy/models/conv_nn.py +112 -0
- hydpy/models/dam/__init__.py +16 -0
- hydpy/models/dam/dam_aides.py +17 -0
- hydpy/models/dam/dam_control.py +346 -0
- hydpy/models/dam/dam_derived.py +559 -0
- hydpy/models/dam/dam_factors.py +46 -0
- hydpy/models/dam/dam_fluxes.py +179 -0
- hydpy/models/dam/dam_inlets.py +29 -0
- hydpy/models/dam/dam_logs.py +52 -0
- hydpy/models/dam/dam_model.py +5011 -0
- hydpy/models/dam/dam_outlets.py +23 -0
- hydpy/models/dam/dam_receivers.py +41 -0
- hydpy/models/dam/dam_senders.py +23 -0
- hydpy/models/dam/dam_solver.py +75 -0
- hydpy/models/dam/dam_states.py +11 -0
- hydpy/models/dam_llake.py +499 -0
- hydpy/models/dam_lreservoir.py +548 -0
- hydpy/models/dam_lretention.py +343 -0
- hydpy/models/dam_pump.py +278 -0
- hydpy/models/dam_pump_sluice.py +339 -0
- hydpy/models/dam_sluice.py +319 -0
- hydpy/models/dam_v001.py +1127 -0
- hydpy/models/dam_v002.py +381 -0
- hydpy/models/dam_v003.py +422 -0
- hydpy/models/dam_v004.py +665 -0
- hydpy/models/dam_v005.py +479 -0
- hydpy/models/dummy/__init__.py +15 -0
- hydpy/models/dummy/dummy_control.py +22 -0
- hydpy/models/dummy/dummy_fluxes.py +11 -0
- hydpy/models/dummy/dummy_inlets.py +11 -0
- hydpy/models/dummy/dummy_inputs.py +41 -0
- hydpy/models/dummy/dummy_model.py +196 -0
- hydpy/models/dummy/dummy_outlets.py +11 -0
- hydpy/models/dummy_interceptedwater.py +85 -0
- hydpy/models/dummy_node2node.py +83 -0
- hydpy/models/dummy_snowalbedo.py +84 -0
- hydpy/models/dummy_snowcover.py +84 -0
- hydpy/models/dummy_snowycanopy.py +86 -0
- hydpy/models/dummy_soilwater.py +85 -0
- hydpy/models/evap/__init__.py +13 -0
- hydpy/models/evap/evap_control.py +354 -0
- hydpy/models/evap/evap_derived.py +236 -0
- hydpy/models/evap/evap_factors.py +188 -0
- hydpy/models/evap/evap_fixed.py +68 -0
- hydpy/models/evap/evap_fluxes.py +150 -0
- hydpy/models/evap/evap_inputs.py +54 -0
- hydpy/models/evap/evap_logs.py +91 -0
- hydpy/models/evap/evap_masks.py +48 -0
- hydpy/models/evap/evap_model.py +9170 -0
- hydpy/models/evap/evap_parameters.py +149 -0
- hydpy/models/evap/evap_sequences.py +32 -0
- hydpy/models/evap/evap_states.py +18 -0
- hydpy/models/evap_aet_hbv96.py +372 -0
- hydpy/models/evap_aet_minhas.py +331 -0
- hydpy/models/evap_aet_morsim.py +627 -0
- hydpy/models/evap_pet_ambav1.py +483 -0
- hydpy/models/evap_pet_hbv96.py +147 -0
- hydpy/models/evap_pet_m.py +94 -0
- hydpy/models/evap_pet_mlc.py +107 -0
- hydpy/models/evap_ret_fao56.py +265 -0
- hydpy/models/evap_ret_io.py +74 -0
- hydpy/models/evap_ret_tw2002.py +165 -0
- hydpy/models/exch/__init__.py +14 -0
- hydpy/models/exch/exch_control.py +262 -0
- hydpy/models/exch/exch_derived.py +36 -0
- hydpy/models/exch/exch_factors.py +26 -0
- hydpy/models/exch/exch_fluxes.py +48 -0
- hydpy/models/exch/exch_inlets.py +11 -0
- hydpy/models/exch/exch_logs.py +12 -0
- hydpy/models/exch/exch_model.py +451 -0
- hydpy/models/exch/exch_outlets.py +17 -0
- hydpy/models/exch/exch_receivers.py +17 -0
- hydpy/models/exch_branch_hbv96.py +186 -0
- hydpy/models/exch_waterlevel.py +73 -0
- hydpy/models/exch_weir_hbv96.py +609 -0
- hydpy/models/ga/__init__.py +14 -0
- hydpy/models/ga/ga_aides.py +17 -0
- hydpy/models/ga/ga_control.py +208 -0
- hydpy/models/ga/ga_derived.py +77 -0
- hydpy/models/ga/ga_fluxes.py +83 -0
- hydpy/models/ga/ga_inputs.py +26 -0
- hydpy/models/ga/ga_logs.py +17 -0
- hydpy/models/ga/ga_model.py +2952 -0
- hydpy/models/ga/ga_states.py +87 -0
- hydpy/models/ga_garto.py +1001 -0
- hydpy/models/ga_garto_submodel1.py +79 -0
- hydpy/models/gland/__init__.py +14 -0
- hydpy/models/gland/gland_control.py +90 -0
- hydpy/models/gland/gland_derived.py +113 -0
- hydpy/models/gland/gland_fluxes.py +137 -0
- hydpy/models/gland/gland_inputs.py +12 -0
- hydpy/models/gland/gland_model.py +1439 -0
- hydpy/models/gland/gland_outlets.py +11 -0
- hydpy/models/gland/gland_states.py +90 -0
- hydpy/models/gland_gr4.py +501 -0
- hydpy/models/gland_gr5.py +463 -0
- hydpy/models/gland_gr6.py +487 -0
- hydpy/models/hland/__init__.py +20 -0
- hydpy/models/hland/hland_aides.py +19 -0
- hydpy/models/hland/hland_constants.py +37 -0
- hydpy/models/hland/hland_control.py +1530 -0
- hydpy/models/hland/hland_derived.py +683 -0
- hydpy/models/hland/hland_factors.py +57 -0
- hydpy/models/hland/hland_fixed.py +42 -0
- hydpy/models/hland/hland_fluxes.py +279 -0
- hydpy/models/hland/hland_inputs.py +19 -0
- hydpy/models/hland/hland_masks.py +107 -0
- hydpy/models/hland/hland_model.py +4664 -0
- hydpy/models/hland/hland_outlets.py +11 -0
- hydpy/models/hland/hland_parameters.py +227 -0
- hydpy/models/hland/hland_sequences.py +382 -0
- hydpy/models/hland/hland_states.py +236 -0
- hydpy/models/hland_96.py +1812 -0
- hydpy/models/hland_96c.py +1196 -0
- hydpy/models/hland_96p.py +1204 -0
- hydpy/models/kinw/__init__.py +18 -0
- hydpy/models/kinw/kinw_aides.py +306 -0
- hydpy/models/kinw/kinw_control.py +270 -0
- hydpy/models/kinw/kinw_derived.py +197 -0
- hydpy/models/kinw/kinw_fixed.py +33 -0
- hydpy/models/kinw/kinw_fluxes.py +37 -0
- hydpy/models/kinw/kinw_inlets.py +11 -0
- hydpy/models/kinw/kinw_model.py +3026 -0
- hydpy/models/kinw/kinw_outlets.py +11 -0
- hydpy/models/kinw/kinw_solver.py +45 -0
- hydpy/models/kinw/kinw_states.py +17 -0
- hydpy/models/kinw_williams.py +1299 -0
- hydpy/models/kinw_williams_ext.py +768 -0
- hydpy/models/lland/__init__.py +42 -0
- hydpy/models/lland/lland_aides.py +38 -0
- hydpy/models/lland/lland_constants.py +88 -0
- hydpy/models/lland/lland_control.py +1329 -0
- hydpy/models/lland/lland_derived.py +380 -0
- hydpy/models/lland/lland_factors.py +18 -0
- hydpy/models/lland/lland_fixed.py +128 -0
- hydpy/models/lland/lland_fluxes.py +626 -0
- hydpy/models/lland/lland_inlets.py +12 -0
- hydpy/models/lland/lland_inputs.py +33 -0
- hydpy/models/lland/lland_logs.py +17 -0
- hydpy/models/lland/lland_masks.py +212 -0
- hydpy/models/lland/lland_model.py +7690 -0
- hydpy/models/lland/lland_outlets.py +12 -0
- hydpy/models/lland/lland_parameters.py +195 -0
- hydpy/models/lland/lland_sequences.py +67 -0
- hydpy/models/lland/lland_states.py +280 -0
- hydpy/models/lland_dd.py +2270 -0
- hydpy/models/lland_knauf.py +2156 -0
- hydpy/models/lland_knauf_ic.py +1920 -0
- hydpy/models/meteo/__init__.py +12 -0
- hydpy/models/meteo/meteo_control.py +154 -0
- hydpy/models/meteo/meteo_derived.py +159 -0
- hydpy/models/meteo/meteo_factors.py +88 -0
- hydpy/models/meteo/meteo_fixed.py +19 -0
- hydpy/models/meteo/meteo_fluxes.py +46 -0
- hydpy/models/meteo/meteo_inputs.py +47 -0
- hydpy/models/meteo/meteo_logs.py +30 -0
- hydpy/models/meteo/meteo_model.py +2904 -0
- hydpy/models/meteo/meteo_parameters.py +14 -0
- hydpy/models/meteo/meteo_sequences.py +22 -0
- hydpy/models/meteo_clear_glob_io.py +77 -0
- hydpy/models/meteo_glob_fao56.py +217 -0
- hydpy/models/meteo_glob_io.py +68 -0
- hydpy/models/meteo_glob_morsim.py +444 -0
- hydpy/models/meteo_precip_io.py +76 -0
- hydpy/models/meteo_psun_sun_glob_io.py +83 -0
- hydpy/models/meteo_sun_fao56.py +188 -0
- hydpy/models/meteo_sun_morsim.py +466 -0
- hydpy/models/meteo_temp_io.py +76 -0
- hydpy/models/musk/__init__.py +15 -0
- hydpy/models/musk/musk_control.py +328 -0
- hydpy/models/musk/musk_derived.py +32 -0
- hydpy/models/musk/musk_factors.py +53 -0
- hydpy/models/musk/musk_fluxes.py +24 -0
- hydpy/models/musk/musk_inlets.py +11 -0
- hydpy/models/musk/musk_masks.py +15 -0
- hydpy/models/musk/musk_model.py +838 -0
- hydpy/models/musk/musk_outlets.py +11 -0
- hydpy/models/musk/musk_sequences.py +88 -0
- hydpy/models/musk/musk_solver.py +68 -0
- hydpy/models/musk/musk_states.py +64 -0
- hydpy/models/musk_classic.py +228 -0
- hydpy/models/musk_mct.py +1247 -0
- hydpy/models/rconc/__init__.py +12 -0
- hydpy/models/rconc/rconc_control.py +473 -0
- hydpy/models/rconc/rconc_derived.py +76 -0
- hydpy/models/rconc/rconc_fluxes.py +19 -0
- hydpy/models/rconc/rconc_logs.py +74 -0
- hydpy/models/rconc/rconc_model.py +260 -0
- hydpy/models/rconc/rconc_states.py +11 -0
- hydpy/models/rconc_nash.py +48 -0
- hydpy/models/rconc_uh.py +53 -0
- hydpy/models/sw1d/__init__.py +17 -0
- hydpy/models/sw1d/sw1d_control.py +356 -0
- hydpy/models/sw1d/sw1d_derived.py +85 -0
- hydpy/models/sw1d/sw1d_factors.py +78 -0
- hydpy/models/sw1d/sw1d_fixed.py +12 -0
- hydpy/models/sw1d/sw1d_fluxes.py +55 -0
- hydpy/models/sw1d/sw1d_inlets.py +17 -0
- hydpy/models/sw1d/sw1d_model.py +3385 -0
- hydpy/models/sw1d/sw1d_outlets.py +11 -0
- hydpy/models/sw1d/sw1d_receivers.py +11 -0
- hydpy/models/sw1d/sw1d_senders.py +11 -0
- hydpy/models/sw1d/sw1d_states.py +23 -0
- hydpy/models/sw1d_channel.py +2051 -0
- hydpy/models/sw1d_gate_out.py +599 -0
- hydpy/models/sw1d_lias.py +105 -0
- hydpy/models/sw1d_lias_sluice.py +531 -0
- hydpy/models/sw1d_network.py +1219 -0
- hydpy/models/sw1d_pump.py +448 -0
- hydpy/models/sw1d_q_in.py +79 -0
- hydpy/models/sw1d_q_out.py +81 -0
- hydpy/models/sw1d_storage.py +78 -0
- hydpy/models/sw1d_weir_out.py +75 -0
- hydpy/models/test/__init__.py +14 -0
- hydpy/models/test/test_control.py +28 -0
- hydpy/models/test/test_fluxes.py +17 -0
- hydpy/models/test/test_model.py +201 -0
- hydpy/models/test/test_solver.py +48 -0
- hydpy/models/test/test_states.py +17 -0
- hydpy/models/test_discontinous.py +46 -0
- hydpy/models/test_stiff0d.py +47 -0
- hydpy/models/test_stiff1d.py +42 -0
- hydpy/models/whmod/__init__.py +21 -0
- hydpy/models/whmod/whmod_constants.py +77 -0
- hydpy/models/whmod/whmod_control.py +333 -0
- hydpy/models/whmod/whmod_derived.py +210 -0
- hydpy/models/whmod/whmod_factors.py +9 -0
- hydpy/models/whmod/whmod_fluxes.py +105 -0
- hydpy/models/whmod/whmod_inputs.py +15 -0
- hydpy/models/whmod/whmod_masks.py +178 -0
- hydpy/models/whmod/whmod_model.py +2091 -0
- hydpy/models/whmod/whmod_parameters.py +155 -0
- hydpy/models/whmod/whmod_sequences.py +193 -0
- hydpy/models/whmod/whmod_states.py +73 -0
- hydpy/models/whmod_rural.py +794 -0
- hydpy/models/whmod_urban.py +1011 -0
- hydpy/models/wland/__init__.py +43 -0
- hydpy/models/wland/wland_aides.py +55 -0
- hydpy/models/wland/wland_constants.py +103 -0
- hydpy/models/wland/wland_control.py +508 -0
- hydpy/models/wland/wland_derived.py +330 -0
- hydpy/models/wland/wland_factors.py +11 -0
- hydpy/models/wland/wland_fixed.py +12 -0
- hydpy/models/wland/wland_fluxes.py +166 -0
- hydpy/models/wland/wland_inputs.py +33 -0
- hydpy/models/wland/wland_masks.py +54 -0
- hydpy/models/wland/wland_model.py +3755 -0
- hydpy/models/wland/wland_outlets.py +11 -0
- hydpy/models/wland/wland_parameters.py +214 -0
- hydpy/models/wland/wland_sequences.py +108 -0
- hydpy/models/wland/wland_solver.py +45 -0
- hydpy/models/wland/wland_states.py +56 -0
- hydpy/models/wland_gd.py +888 -0
- hydpy/models/wland_wag.py +1244 -0
- hydpy/models/wq/__init__.py +14 -0
- hydpy/models/wq/wq_control.py +117 -0
- hydpy/models/wq/wq_derived.py +182 -0
- hydpy/models/wq/wq_factors.py +79 -0
- hydpy/models/wq/wq_fluxes.py +17 -0
- hydpy/models/wq/wq_model.py +1889 -0
- hydpy/models/wq_trapeze.py +168 -0
- hydpy/models/wq_trapeze_strickler.py +101 -0
- hydpy/models/wq_walrus.py +57 -0
- hydpy/py.typed +0 -0
- hydpy/tests/.coveragerc +22 -0
- hydpy/tests/__init__.py +0 -0
- hydpy/tests/check_consistency.py +32 -0
- hydpy/tests/hydpydoctestcustomize.pth +1 -0
- hydpy/tests/hydpydoctestcustomize.py +15 -0
- hydpy/tests/iotesting/__init__.py +0 -0
- hydpy/tests/run_doctests.py +233 -0
- hydpy-6.2.dev1.data/scripts/hyd.py +277 -0
- hydpy-6.2.dev1.dist-info/LICENSE +165 -0
- hydpy-6.2.dev1.dist-info/METADATA +163 -0
- hydpy-6.2.dev1.dist-info/RECORD +890 -0
- hydpy-6.2.dev1.dist-info/WHEEL +5 -0
- hydpy-6.2.dev1.dist-info/licenses_hydpy_installer.txt +42 -0
- 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
|
+
)
|