epyt-flow 0.7.3__tar.gz → 0.8.1__tar.gz
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.
- epyt_flow-0.8.1/CITATION.cff +61 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/PKG-INFO +20 -19
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/README.md +17 -18
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/REQUIREMENTS.txt +2 -0
- epyt_flow-0.8.1/epyt_flow/VERSION +1 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/data/benchmarks/leakdb.py +2 -2
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/data/networks.py +14 -26
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/gym/scenario_control_env.py +129 -10
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/serialization.py +10 -3
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/events/__init__.py +1 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/events/leakages.py +55 -12
- epyt_flow-0.8.1/epyt_flow/simulation/events/quality_events.py +194 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/events/system_event.py +5 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/scada/scada_data.py +512 -64
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/scada/scada_data_export.py +7 -5
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/scenario_config.py +13 -2
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/scenario_simulator.py +275 -187
- epyt_flow-0.8.1/epyt_flow/simulation/scenario_visualizer.py +1307 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow.egg-info/PKG-INFO +20 -19
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow.egg-info/SOURCES.txt +1 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow.egg-info/requires.txt +2 -0
- epyt_flow-0.7.3/CITATION.cff +0 -37
- epyt_flow-0.7.3/epyt_flow/VERSION +0 -1
- epyt_flow-0.7.3/epyt_flow/simulation/scenario_visualizer.py +0 -61
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/CODE_OF_CONDUCT.md +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/LICENSE +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/MANIFEST.in +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/genmmd.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/hash.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/hash.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/input1.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/input2.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/input3.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/main.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/output.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/project.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/quality.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/report.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/rules.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/text.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET/SRC_engines/types.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/MSX_Updates.txt +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/dispersion.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/hash.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/hash.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx_export.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/mempool.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/mempool.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxchem.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxcompiler.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxdict.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxdispersion.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxerr.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxfile.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxinp.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxout.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxproj.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxqual.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxrpt.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxtank.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxtoolkit.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxtypes.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxutils.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/msxutils.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/newton.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/newton.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/rk5.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/rk5.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/ros2.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/ros2.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/smatrix.c +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/Src/smatrix.h +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/EPANET-MSX/readme.txt +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/compile_linux.sh +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/EPANET/compile_macos.sh +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/__init__.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/data/__init__.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/data/benchmarks/__init__.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/data/benchmarks/batadal.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/data/benchmarks/batadal_data.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/data/benchmarks/battledim.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/data/benchmarks/battledim_data.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/data/benchmarks/gecco_water_quality.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/data/benchmarks/leakdb_data.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/data/benchmarks/water_usage.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/gym/__init__.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/gym/control_gyms.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/metrics.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/models/__init__.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/models/event_detector.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/models/sensor_interpolation_detector.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/rest_api/__init__.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/rest_api/base_handler.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/rest_api/res_manager.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/rest_api/scada_data/__init__.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/rest_api/scada_data/data_handlers.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/rest_api/scada_data/export_handlers.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/rest_api/scada_data/handlers.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/rest_api/scenario/__init__.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/rest_api/scenario/event_handlers.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/rest_api/scenario/handlers.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/rest_api/scenario/simulation_handlers.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/rest_api/scenario/uncertainty_handlers.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/rest_api/server.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/__init__.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/events/actuator_events.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/events/event.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/events/sensor_faults.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/events/sensor_reading_attack.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/events/sensor_reading_event.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/parallel_simulation.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/scada/__init__.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/scada/advanced_control.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/simulation/sensor_config.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/topology.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/uncertainty/__init__.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/uncertainty/model_uncertainty.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/uncertainty/sensor_noise.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/uncertainty/uncertainties.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/uncertainty/utils.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow/utils.py +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow.egg-info/dependency_links.txt +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/epyt_flow.egg-info/top_level.txt +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/pyproject.toml +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/setup.cfg +0 -0
- {epyt_flow-0.7.3 → epyt_flow-0.8.1}/setup.py +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
cff-version: "1.2.0"
|
|
2
|
+
authors:
|
|
3
|
+
- family-names: Artelt
|
|
4
|
+
given-names: André
|
|
5
|
+
orcid: "https://orcid.org/0000-0002-2426-3126"
|
|
6
|
+
- family-names: Kyriakou
|
|
7
|
+
given-names: Marios S.
|
|
8
|
+
orcid: "https://orcid.org/0000-0002-2324-8661"
|
|
9
|
+
- family-names: Vrachimis
|
|
10
|
+
given-names: Stelios G.
|
|
11
|
+
orcid: "https://orcid.org/0000-0001-8862-5205"
|
|
12
|
+
- family-names: Eliades
|
|
13
|
+
given-names: Demetrios G.
|
|
14
|
+
orcid: "https://orcid.org/0000-0001-6184-6366"
|
|
15
|
+
- family-names: Hammer
|
|
16
|
+
given-names: Barbara
|
|
17
|
+
orcid: "https://orcid.org/0000-0002-0935-5591"
|
|
18
|
+
- family-names: Polycarpou
|
|
19
|
+
given-names: Marios M.
|
|
20
|
+
orcid: "https://orcid.org/0000-0001-6495-9171"
|
|
21
|
+
contact:
|
|
22
|
+
- family-names: Artelt
|
|
23
|
+
given-names: André
|
|
24
|
+
orcid: "https://orcid.org/0000-0002-2426-3126"
|
|
25
|
+
message: If you use this software, please cite our article in the
|
|
26
|
+
Journal of Open Source Software.
|
|
27
|
+
preferred-citation:
|
|
28
|
+
authors:
|
|
29
|
+
- family-names: Artelt
|
|
30
|
+
given-names: André
|
|
31
|
+
orcid: "https://orcid.org/0000-0002-2426-3126"
|
|
32
|
+
- family-names: Kyriakou
|
|
33
|
+
given-names: Marios S.
|
|
34
|
+
orcid: "https://orcid.org/0000-0002-2324-8661"
|
|
35
|
+
- family-names: Vrachimis
|
|
36
|
+
given-names: Stelios G.
|
|
37
|
+
orcid: "https://orcid.org/0000-0001-8862-5205"
|
|
38
|
+
- family-names: Eliades
|
|
39
|
+
given-names: Demetrios G.
|
|
40
|
+
orcid: "https://orcid.org/0000-0001-6184-6366"
|
|
41
|
+
- family-names: Hammer
|
|
42
|
+
given-names: Barbara
|
|
43
|
+
orcid: "https://orcid.org/0000-0002-0935-5591"
|
|
44
|
+
- family-names: Polycarpou
|
|
45
|
+
given-names: Marios M.
|
|
46
|
+
orcid: "https://orcid.org/0000-0001-6495-9171"
|
|
47
|
+
date-published: 2024-11-12
|
|
48
|
+
doi: 10.21105/joss.07104
|
|
49
|
+
issn: 2475-9066
|
|
50
|
+
issue: 103
|
|
51
|
+
journal: Journal of Open Source Software
|
|
52
|
+
publisher:
|
|
53
|
+
name: Open Journals
|
|
54
|
+
start: 7104
|
|
55
|
+
title: "EPyT-Flow: A Toolkit for Generating Water Distribution Network
|
|
56
|
+
Data"
|
|
57
|
+
type: article
|
|
58
|
+
url: "https://joss.theoj.org/papers/10.21105/joss.07104"
|
|
59
|
+
volume: 9
|
|
60
|
+
title: "EPyT-Flow: A Toolkit for Generating Water Distribution Network
|
|
61
|
+
Data"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: epyt-flow
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.1
|
|
4
4
|
Summary: EPyT-Flow -- EPANET Python Toolkit - Flow
|
|
5
5
|
Author-email: André Artelt <aartelt@techfak.uni-bielefeld.de>, "Marios S. Kyriakou" <kiriakou.marios@ucy.ac.cy>, "Stelios G. Vrachimis" <vrachimis.stelios@ucy.ac.cy>
|
|
6
6
|
License: MIT License
|
|
@@ -31,6 +31,8 @@ Requires-Dist: openpyxl>=3.1.2
|
|
|
31
31
|
Requires-Dist: falcon>=3.1.3
|
|
32
32
|
Requires-Dist: multiprocess>=0.70.16
|
|
33
33
|
Requires-Dist: geopandas>=0.14.4
|
|
34
|
+
Requires-Dist: svgpath2mpl>=1.0.0
|
|
35
|
+
Requires-Dist: Deprecated>=1.2.14
|
|
34
36
|
Requires-Dist: psutil
|
|
35
37
|
|
|
36
38
|
[](https://pypi.org/project/epyt-flow/)
|
|
@@ -40,6 +42,7 @@ Requires-Dist: psutil
|
|
|
40
42
|
[](https://epyt-flow.readthedocs.io/en/stable/?badge=stable)
|
|
41
43
|
[](https://pepy.tech/project/epyt-flow)
|
|
42
44
|
[](https://pepy.tech/project/epyt-flow)
|
|
45
|
+
[](https://doi.org/10.21105/joss.07104)
|
|
43
46
|
|
|
44
47
|
# EPyT-Flow -- EPANET Python Toolkit - Flow
|
|
45
48
|
|
|
@@ -121,7 +124,7 @@ pip install .
|
|
|
121
124
|
```python
|
|
122
125
|
from epyt_flow.data.benchmarks import load_leakdb_scenarios
|
|
123
126
|
from epyt_flow.simulation import ScenarioSimulator
|
|
124
|
-
from epyt_flow.utils import to_seconds
|
|
127
|
+
from epyt_flow.utils import to_seconds
|
|
125
128
|
|
|
126
129
|
|
|
127
130
|
if __name__ == "__main__":
|
|
@@ -144,16 +147,10 @@ if __name__ == "__main__":
|
|
|
144
147
|
|
|
145
148
|
# Print & plot sensor readings over the entire simulation
|
|
146
149
|
print(f"Pressure readings: {scada_data.get_data_pressures()}")
|
|
147
|
-
|
|
148
|
-
labels=[f"Node {n_id}" for n_id in
|
|
149
|
-
scada_data.sensor_config.pressure_sensors],
|
|
150
|
-
x_axis_label="Time (30min steps)",
|
|
151
|
-
y_axis_label="Pressure in $m$")
|
|
150
|
+
scada_data.plot_pressures()
|
|
152
151
|
|
|
153
152
|
print(f"Flow readings: {scada_data.get_data_flows()}")
|
|
154
|
-
|
|
155
|
-
x_axis_label="Time (30min steps)",
|
|
156
|
-
y_axis_label="Flow rate in $m^3/h$")
|
|
153
|
+
scada_data.plot_flows()
|
|
157
154
|
```
|
|
158
155
|
### Generated plots
|
|
159
156
|
|
|
@@ -194,15 +191,19 @@ MIT license -- see [LICENSE](LICENSE)
|
|
|
194
191
|
|
|
195
192
|
If you use this software, please cite it as follows:
|
|
196
193
|
|
|
197
|
-
```
|
|
198
|
-
@
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
194
|
+
```bibtex
|
|
195
|
+
@article{Artelt2024,
|
|
196
|
+
doi = {10.21105/joss.07104},
|
|
197
|
+
url = {https://doi.org/10.21105/joss.07104},
|
|
198
|
+
year = {2024},
|
|
199
|
+
publisher = {The Open Journal},
|
|
200
|
+
volume = {9},
|
|
201
|
+
number = {103},
|
|
202
|
+
pages = {7104},
|
|
203
|
+
author = {André Artelt and Marios S. Kyriakou and Stelios G. Vrachimis and Demetrios G. Eliades and Barbara Hammer and Marios M. Polycarpou},
|
|
204
|
+
title = {EPyT-Flow: A Toolkit for Generating Water Distribution Network Data},
|
|
205
|
+
journal = {Journal of Open Source Software}
|
|
206
|
+
}
|
|
206
207
|
```
|
|
207
208
|
|
|
208
209
|
## How to get Support?
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
[](https://epyt-flow.readthedocs.io/en/stable/?badge=stable)
|
|
6
6
|
[](https://pepy.tech/project/epyt-flow)
|
|
7
7
|
[](https://pepy.tech/project/epyt-flow)
|
|
8
|
+
[](https://doi.org/10.21105/joss.07104)
|
|
8
9
|
|
|
9
10
|
# EPyT-Flow -- EPANET Python Toolkit - Flow
|
|
10
11
|
|
|
@@ -86,7 +87,7 @@ pip install .
|
|
|
86
87
|
```python
|
|
87
88
|
from epyt_flow.data.benchmarks import load_leakdb_scenarios
|
|
88
89
|
from epyt_flow.simulation import ScenarioSimulator
|
|
89
|
-
from epyt_flow.utils import to_seconds
|
|
90
|
+
from epyt_flow.utils import to_seconds
|
|
90
91
|
|
|
91
92
|
|
|
92
93
|
if __name__ == "__main__":
|
|
@@ -109,16 +110,10 @@ if __name__ == "__main__":
|
|
|
109
110
|
|
|
110
111
|
# Print & plot sensor readings over the entire simulation
|
|
111
112
|
print(f"Pressure readings: {scada_data.get_data_pressures()}")
|
|
112
|
-
|
|
113
|
-
labels=[f"Node {n_id}" for n_id in
|
|
114
|
-
scada_data.sensor_config.pressure_sensors],
|
|
115
|
-
x_axis_label="Time (30min steps)",
|
|
116
|
-
y_axis_label="Pressure in $m$")
|
|
113
|
+
scada_data.plot_pressures()
|
|
117
114
|
|
|
118
115
|
print(f"Flow readings: {scada_data.get_data_flows()}")
|
|
119
|
-
|
|
120
|
-
x_axis_label="Time (30min steps)",
|
|
121
|
-
y_axis_label="Flow rate in $m^3/h$")
|
|
116
|
+
scada_data.plot_flows()
|
|
122
117
|
```
|
|
123
118
|
### Generated plots
|
|
124
119
|
|
|
@@ -159,15 +154,19 @@ MIT license -- see [LICENSE](LICENSE)
|
|
|
159
154
|
|
|
160
155
|
If you use this software, please cite it as follows:
|
|
161
156
|
|
|
162
|
-
```
|
|
163
|
-
@
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
157
|
+
```bibtex
|
|
158
|
+
@article{Artelt2024,
|
|
159
|
+
doi = {10.21105/joss.07104},
|
|
160
|
+
url = {https://doi.org/10.21105/joss.07104},
|
|
161
|
+
year = {2024},
|
|
162
|
+
publisher = {The Open Journal},
|
|
163
|
+
volume = {9},
|
|
164
|
+
number = {103},
|
|
165
|
+
pages = {7104},
|
|
166
|
+
author = {André Artelt and Marios S. Kyriakou and Stelios G. Vrachimis and Demetrios G. Eliades and Barbara Hammer and Marios M. Polycarpou},
|
|
167
|
+
title = {EPyT-Flow: A Toolkit for Generating Water Distribution Network Data},
|
|
168
|
+
journal = {Journal of Open Source Software}
|
|
169
|
+
}
|
|
171
170
|
```
|
|
172
171
|
|
|
173
172
|
## How to get Support?
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.8.1
|
|
@@ -491,9 +491,9 @@ def load_scenarios(scenarios_id: list[int], use_net1: bool = True,
|
|
|
491
491
|
|
|
492
492
|
return dem_final
|
|
493
493
|
|
|
494
|
-
week_pattern_url = "https://
|
|
494
|
+
week_pattern_url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/CCWI-WDSA2018/" +\
|
|
495
495
|
"Dataset_Generator_Py3/weekPat_30min.mat"
|
|
496
|
-
year_offset_url = "https://
|
|
496
|
+
year_offset_url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/CCWI-WDSA2018/" +\
|
|
497
497
|
"Dataset_Generator_Py3/yearOffset_30min.mat"
|
|
498
498
|
|
|
499
499
|
download_if_necessary(os.path.join(download_dir, "weekPat_30min.mat"),
|
|
@@ -153,8 +153,7 @@ def load_net1(download_dir: str = get_temp_folder(), verbose: bool = True,
|
|
|
153
153
|
:class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`.
|
|
154
154
|
"""
|
|
155
155
|
f_in = os.path.join(download_dir, "Net1.inp")
|
|
156
|
-
url = "https://
|
|
157
|
-
"asce-tf-wdst/Net1.inp"
|
|
156
|
+
url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/Net1.inp"
|
|
158
157
|
|
|
159
158
|
download_if_necessary(f_in, url, verbose)
|
|
160
159
|
return load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -201,8 +200,7 @@ def load_net2(download_dir: str = get_temp_folder(), verbose: bool = True,
|
|
|
201
200
|
:class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`.
|
|
202
201
|
"""
|
|
203
202
|
f_in = os.path.join(download_dir, "Net2.inp")
|
|
204
|
-
url = "https://
|
|
205
|
-
"asce-tf-wdst/Net2.inp"
|
|
203
|
+
url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/Net2.inp"
|
|
206
204
|
|
|
207
205
|
download_if_necessary(f_in, url, verbose)
|
|
208
206
|
return load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -249,8 +247,7 @@ def load_net3(download_dir: str = get_temp_folder(), verbose: bool = True,
|
|
|
249
247
|
:class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`.
|
|
250
248
|
"""
|
|
251
249
|
f_in = os.path.join(download_dir, "Net3.inp")
|
|
252
|
-
url = "https://
|
|
253
|
-
"asce-tf-wdst/Net3.inp"
|
|
250
|
+
url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/Net3.inp"
|
|
254
251
|
|
|
255
252
|
download_if_necessary(f_in, url, verbose)
|
|
256
253
|
return load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -297,7 +294,7 @@ def load_net6(download_dir: str = get_temp_folder(), verbose: bool = True,
|
|
|
297
294
|
:class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`.
|
|
298
295
|
"""
|
|
299
296
|
f_in = os.path.join(download_dir, "Net6.inp")
|
|
300
|
-
url = "https://
|
|
297
|
+
url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/Net6.inp"
|
|
301
298
|
|
|
302
299
|
download_if_necessary(f_in, url, verbose)
|
|
303
300
|
return load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -344,8 +341,7 @@ def load_richmond(download_dir: str = get_temp_folder(), verbose: bool = True,
|
|
|
344
341
|
:class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`.
|
|
345
342
|
"""
|
|
346
343
|
f_in = os.path.join(download_dir, "Richmond_standard.inp")
|
|
347
|
-
url = "https://
|
|
348
|
-
"exeter-benchmarks/Richmond_standard.inp"
|
|
344
|
+
url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/Richmond_standard.inp"
|
|
349
345
|
|
|
350
346
|
download_if_necessary(f_in, url, verbose)
|
|
351
347
|
return load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -392,8 +388,7 @@ def load_micropolis(download_dir: str = get_temp_folder(), verbose: bool = True,
|
|
|
392
388
|
:class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`.
|
|
393
389
|
"""
|
|
394
390
|
f_in = os.path.join(download_dir, "MICROPOLIS_v1.inp")
|
|
395
|
-
url = "https://
|
|
396
|
-
"MICROPOLIS_v1.inp"
|
|
391
|
+
url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/MICROPOLIS_v1.inp"
|
|
397
392
|
|
|
398
393
|
download_if_necessary(f_in, url, verbose)
|
|
399
394
|
return load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -440,8 +435,7 @@ def load_balerma(download_dir: str = get_temp_folder(), verbose: bool = True,
|
|
|
440
435
|
:class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`.
|
|
441
436
|
"""
|
|
442
437
|
f_in = os.path.join(download_dir, "Balerma.inp")
|
|
443
|
-
url = "https://
|
|
444
|
-
"asce-tf-wdst/Balerma.inp"
|
|
438
|
+
url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/Balerma.inp"
|
|
445
439
|
|
|
446
440
|
download_if_necessary(f_in, url, verbose)
|
|
447
441
|
return load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -488,8 +482,7 @@ def load_rural(download_dir: str = get_temp_folder(), verbose: bool = True,
|
|
|
488
482
|
:class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`.
|
|
489
483
|
"""
|
|
490
484
|
f_in = os.path.join(download_dir, "RuralNetwork.inp")
|
|
491
|
-
url = "https://
|
|
492
|
-
"asce-tf-wdst/RuralNetwork.inp"
|
|
485
|
+
url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/RuralNetwork.inp"
|
|
493
486
|
|
|
494
487
|
download_if_necessary(f_in, url, verbose)
|
|
495
488
|
return load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -536,8 +529,7 @@ def load_bwsn1(download_dir: str = get_temp_folder(), verbose: bool = True,
|
|
|
536
529
|
:class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`.
|
|
537
530
|
"""
|
|
538
531
|
f_in = os.path.join(download_dir, "BWSN_Network_1.inp")
|
|
539
|
-
url = "https://
|
|
540
|
-
"asce-tf-wdst/BWSN_Network_1.inp"
|
|
532
|
+
url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/BWSN_Network_1.inp"
|
|
541
533
|
|
|
542
534
|
download_if_necessary(f_in, url, verbose)
|
|
543
535
|
return load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -584,8 +576,7 @@ def load_bwsn2(download_dir: str = get_temp_folder(), verbose: bool = True,
|
|
|
584
576
|
:class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`.
|
|
585
577
|
"""
|
|
586
578
|
f_in = os.path.join(download_dir, "BWSN_Network_2.inp")
|
|
587
|
-
url = "https://
|
|
588
|
-
"asce-tf-wdst/BWSN_Network_2.inp"
|
|
579
|
+
url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/BWSN_Network_2.inp"
|
|
589
580
|
|
|
590
581
|
download_if_necessary(f_in, url, verbose)
|
|
591
582
|
return load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -632,8 +623,7 @@ def load_anytown(download_dir: str = get_temp_folder(), verbose: bool = True,
|
|
|
632
623
|
:class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`.
|
|
633
624
|
"""
|
|
634
625
|
f_in = os.path.join(download_dir, "Anytown.inp")
|
|
635
|
-
url = "https://
|
|
636
|
-
"asce-tf-wdst/Anytown.inp"
|
|
626
|
+
url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/Anytown.inp"
|
|
637
627
|
|
|
638
628
|
download_if_necessary(f_in, url, verbose)
|
|
639
629
|
return load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -727,7 +717,7 @@ def load_ctown(download_dir: str = get_temp_folder(), verbose: bool = True,
|
|
|
727
717
|
:class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`.
|
|
728
718
|
"""
|
|
729
719
|
f_in = os.path.join(download_dir, "CTOWN.INP")
|
|
730
|
-
url = "https://
|
|
720
|
+
url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/CTOWN.INP"
|
|
731
721
|
|
|
732
722
|
download_if_necessary(f_in, url, verbose)
|
|
733
723
|
return load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -783,8 +773,7 @@ def load_kentucky(wdn_id: int = 1, download_dir: str = get_temp_folder(),
|
|
|
783
773
|
raise ValueError(f"Unknown network 'ky{wdn_id}.inp'")
|
|
784
774
|
|
|
785
775
|
f_in = os.path.join(download_dir, f"ky{wdn_id}.inp")
|
|
786
|
-
url = "https://
|
|
787
|
-
f"asce-tf-wdst/ky{wdn_id}.inp"
|
|
776
|
+
url = f"https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/ky{wdn_id}.inp"
|
|
788
777
|
|
|
789
778
|
download_if_necessary(f_in, url, verbose)
|
|
790
779
|
return load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -836,8 +825,7 @@ def load_hanoi(download_dir: str = get_temp_folder(),
|
|
|
836
825
|
:class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`.
|
|
837
826
|
"""
|
|
838
827
|
f_in = os.path.join(download_dir, "Hanoi.inp")
|
|
839
|
-
url = "https://
|
|
840
|
-
"asce-tf-wdst/Hanoi.inp"
|
|
828
|
+
url = "https://filedn.com/lumBFq2P9S74PNoLPWtzxG4/EPyT-Flow/Networks/Hanoi.inp"
|
|
841
829
|
|
|
842
830
|
download_if_necessary(f_in, url, verbose)
|
|
843
831
|
config = load_inp(f_in, flow_units_id=flow_units_id)
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Module provides a base class for control environments.
|
|
3
3
|
"""
|
|
4
|
+
import os
|
|
5
|
+
import uuid
|
|
4
6
|
from abc import abstractmethod, ABC
|
|
5
7
|
from typing import Union
|
|
6
8
|
import warnings
|
|
7
9
|
import numpy as np
|
|
8
10
|
|
|
9
|
-
from ..simulation import ScenarioSimulator, ScenarioConfig, ScadaData
|
|
11
|
+
from ..simulation import ScenarioSimulator, ScenarioConfig, ScadaData, ToolkitConstants
|
|
12
|
+
from ..utils import get_temp_folder
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
class ScenarioControlEnv(ABC):
|
|
@@ -21,12 +24,32 @@ class ScenarioControlEnv(ABC):
|
|
|
21
24
|
If True, environment is automatically reset if terminated.
|
|
22
25
|
|
|
23
26
|
The default is False.
|
|
27
|
+
|
|
28
|
+
Attributes
|
|
29
|
+
----------
|
|
30
|
+
_scenario_sim : :class:`~epyt_flow.simulation.scenario_simulator.ScenarioSimulator`, protected
|
|
31
|
+
Scenario simulator of the control scenario.
|
|
32
|
+
_scenario_config : :class:`~epyt_flow.simulation.scenario_config.ScenarioConfig`
|
|
33
|
+
Scenario configuration.
|
|
34
|
+
_sim_generator : Generator[Union[:class:`~epyt_flow.simulation.scada.scada_data.ScadaData`, dict], bool, None], protected
|
|
35
|
+
Generator for running the step-wise simulation.
|
|
36
|
+
_hydraulic_scada_data : :class:`~epyt_flow.simulation.scada.scada_data.ScadaData`, protected
|
|
37
|
+
SCADA data from the hydraulic simulation -- only used if EPANET-MSX is used in the control scenario.
|
|
24
38
|
"""
|
|
25
39
|
def __init__(self, scenario_config: ScenarioConfig, autoreset: bool = False, **kwds):
|
|
26
|
-
|
|
40
|
+
if not isinstance(scenario_config, ScenarioConfig):
|
|
41
|
+
raise TypeError("'scenario_config' must be an instance of " +
|
|
42
|
+
"'epyt_flow.simulation.ScenarioConfig' " +
|
|
43
|
+
"but not of '{type(scenario_config)}'")
|
|
44
|
+
if not isinstance(autoreset, bool):
|
|
45
|
+
raise TypeError("'autoreset' must be an instance of 'bool' " +
|
|
46
|
+
f"but not of '{type(autoreset)}'")
|
|
47
|
+
|
|
48
|
+
self._scenario_config = scenario_config
|
|
27
49
|
self._scenario_sim = None
|
|
28
50
|
self._sim_generator = None
|
|
29
51
|
self.__autoreset = autoreset
|
|
52
|
+
self._hydraulic_scada_data = None
|
|
30
53
|
|
|
31
54
|
super().__init__(**kwds)
|
|
32
55
|
|
|
@@ -54,15 +77,27 @@ class ScenarioControlEnv(ABC):
|
|
|
54
77
|
"""
|
|
55
78
|
try:
|
|
56
79
|
if self._sim_generator is not None:
|
|
57
|
-
self._sim_generator.send(True)
|
|
58
80
|
next(self._sim_generator)
|
|
81
|
+
self._sim_generator.send(True)
|
|
59
82
|
except StopIteration:
|
|
60
83
|
pass
|
|
61
84
|
|
|
62
85
|
if self._scenario_sim is not None:
|
|
63
86
|
self._scenario_sim.close()
|
|
64
87
|
|
|
65
|
-
def
|
|
88
|
+
def contains_events(self) -> bool:
|
|
89
|
+
"""
|
|
90
|
+
Check if the scenario contains any events.
|
|
91
|
+
|
|
92
|
+
Returns
|
|
93
|
+
-------
|
|
94
|
+
`bool`
|
|
95
|
+
True is the scenario contains any events, False otherwise.
|
|
96
|
+
"""
|
|
97
|
+
return len(self._scenario_config.system_events) != 0 or \
|
|
98
|
+
len(self._scenario_config.sensor_reading_events) != 0
|
|
99
|
+
|
|
100
|
+
def reset(self) -> Union[tuple[ScadaData, bool], ScadaData]:
|
|
66
101
|
"""
|
|
67
102
|
Resets the environment (i.e. simulation).
|
|
68
103
|
|
|
@@ -75,20 +110,38 @@ class ScenarioControlEnv(ABC):
|
|
|
75
110
|
self._scenario_sim.close()
|
|
76
111
|
|
|
77
112
|
self._scenario_sim = ScenarioSimulator(
|
|
78
|
-
scenario_config=self.
|
|
79
|
-
|
|
113
|
+
scenario_config=self._scenario_config)
|
|
114
|
+
|
|
115
|
+
if self._scenario_sim.f_msx_in is not None:
|
|
116
|
+
# Run hydraulic simulation first
|
|
117
|
+
hyd_export = os.path.join(get_temp_folder(), f"epytflow_env_MSX_{uuid.uuid4()}.hyd")
|
|
118
|
+
sim = self._scenario_sim.run_hydraulic_simulation
|
|
119
|
+
self._hydraulic_scada_data = sim(hyd_export=hyd_export)
|
|
120
|
+
|
|
121
|
+
# Run advanced quality analysis (EPANET-MSX) on top of the computed hydraulics
|
|
122
|
+
gen = self._scenario_sim.run_advanced_quality_simulation_as_generator
|
|
123
|
+
self._sim_generator = gen(hyd_export, support_abort=True)
|
|
124
|
+
else:
|
|
125
|
+
gen = self._scenario_sim.run_hydraulic_simulation_as_generator
|
|
126
|
+
self._sim_generator = gen(support_abort=True)
|
|
80
127
|
|
|
81
128
|
return self._next_sim_itr()
|
|
82
129
|
|
|
83
|
-
def _next_sim_itr(self) -> ScadaData:
|
|
130
|
+
def _next_sim_itr(self) -> Union[tuple[ScadaData, bool], ScadaData]:
|
|
84
131
|
try:
|
|
85
132
|
next(self._sim_generator)
|
|
86
|
-
|
|
133
|
+
scada_data = self._sim_generator.send(False)
|
|
134
|
+
|
|
135
|
+
if self._scenario_sim.f_msx_in is not None:
|
|
136
|
+
cur_time = int(scada_data.sensor_readings_time[0])
|
|
137
|
+
cur_hyd_scada_data = self._hydraulic_scada_data.\
|
|
138
|
+
extract_time_window(cur_time, cur_time)
|
|
139
|
+
scada_data.join(cur_hyd_scada_data)
|
|
87
140
|
|
|
88
141
|
if self.autoreset is True:
|
|
89
|
-
return
|
|
142
|
+
return scada_data
|
|
90
143
|
else:
|
|
91
|
-
return
|
|
144
|
+
return scada_data, False
|
|
92
145
|
except StopIteration:
|
|
93
146
|
if self.__autoreset is True:
|
|
94
147
|
return self.reset()
|
|
@@ -112,6 +165,10 @@ class ScenarioControlEnv(ABC):
|
|
|
112
165
|
- EN_CLOSED = 0
|
|
113
166
|
- EN_OPEN = 1
|
|
114
167
|
"""
|
|
168
|
+
if self._scenario_sim.f_msx_in is not None:
|
|
169
|
+
raise RuntimeError("Can not execute actions affecting the hydraulics "+
|
|
170
|
+
"when running EPANET-MSX")
|
|
171
|
+
|
|
115
172
|
pump_idx = self._scenario_sim.epanet_api.getLinkPumpNameID().index(pump_id)
|
|
116
173
|
pump_link_idx = self._scenario_sim.epanet_api.getLinkPumpIndex(pump_idx + 1)
|
|
117
174
|
self._scenario_sim.epanet_api.setLinkStatus(pump_link_idx, status)
|
|
@@ -127,6 +184,10 @@ class ScenarioControlEnv(ABC):
|
|
|
127
184
|
speed : `float`
|
|
128
185
|
New pump speed.
|
|
129
186
|
"""
|
|
187
|
+
if self._scenario_sim.f_msx_in is not None:
|
|
188
|
+
raise RuntimeError("Can not execute actions affecting the hydraulics "+
|
|
189
|
+
"when running EPANET-MSX")
|
|
190
|
+
|
|
130
191
|
pump_idx = self._scenario_sim.epanet_api.getLinkPumpNameID().index(pump_id)
|
|
131
192
|
pattern_idx = self._scenario_sim.epanet_api.getLinkPumpPatternIndex(pump_idx + 1)
|
|
132
193
|
|
|
@@ -154,6 +215,10 @@ class ScenarioControlEnv(ABC):
|
|
|
154
215
|
- EN_CLOSED = 0
|
|
155
216
|
- EN_OPEN = 1
|
|
156
217
|
"""
|
|
218
|
+
if self._scenario_sim.f_msx_in is not None:
|
|
219
|
+
raise RuntimeError("Can not execute actions affecting the hydraulics "+
|
|
220
|
+
"when running EPANET-MSX")
|
|
221
|
+
|
|
157
222
|
valve_idx = self._scenario_sim.epanet_api.getLinkValveNameID().index(valve_id)
|
|
158
223
|
valve_link_idx = self._scenario_sim.epanet_api.getLinkValveIndex()[valve_idx]
|
|
159
224
|
self._scenario_sim.epanet_api.setLinkStatus(valve_link_idx, status)
|
|
@@ -173,11 +238,65 @@ class ScenarioControlEnv(ABC):
|
|
|
173
238
|
qual_value : `float`
|
|
174
239
|
New quality source value.
|
|
175
240
|
"""
|
|
241
|
+
if self._scenario_sim.f_msx_in is not None:
|
|
242
|
+
raise RuntimeError("Can not execute actions affecting the hydraulics "+
|
|
243
|
+
"when running EPANET-MSX")
|
|
244
|
+
|
|
176
245
|
node_idx = self._scenario_sim.epanet_api.getNodeIndex(node_id)
|
|
177
246
|
pattern_idx = self._scenario_sim.epanet_api.getPatternIndex(pattern_id)
|
|
178
247
|
self._scenario_sim.epanet_api.setNodeSourceQuality(node_idx, 1)
|
|
179
248
|
self._scenario_sim.epanet_api.setPattern(pattern_idx, np.array([qual_value]))
|
|
180
249
|
|
|
250
|
+
def set_node_species_source_value(self, species_id: str, node_id: str, source_type: int,
|
|
251
|
+
pattern_id: str, source_strength: float) -> None:
|
|
252
|
+
"""
|
|
253
|
+
Sets the species source at a particular node to a specific value -- i.e.
|
|
254
|
+
setting the species injection amount at a particular location.
|
|
255
|
+
|
|
256
|
+
Parameters
|
|
257
|
+
----------
|
|
258
|
+
species_id : `str`
|
|
259
|
+
ID of the species.
|
|
260
|
+
node_id : `str`
|
|
261
|
+
ID of the node.
|
|
262
|
+
source_type : `int`
|
|
263
|
+
Type of the external species injection source -- must be one of
|
|
264
|
+
the following EPANET toolkit constants:
|
|
265
|
+
|
|
266
|
+
- EN_CONCEN = 0
|
|
267
|
+
- EN_MASS = 1
|
|
268
|
+
- EN_SETPOINT = 2
|
|
269
|
+
- EN_FLOWPACED = 3
|
|
270
|
+
|
|
271
|
+
Description:
|
|
272
|
+
|
|
273
|
+
- E_CONCEN Sets the concentration of external inflow entering a node
|
|
274
|
+
- EN_MASS Injects a given mass/minute into a node
|
|
275
|
+
- EN_SETPOINT Sets the concentration leaving a node to a given value
|
|
276
|
+
- EN_FLOWPACED Adds a given value to the concentration leaving a node
|
|
277
|
+
pattern_id : `str`
|
|
278
|
+
ID of the source pattern.
|
|
279
|
+
source_strength : `float`
|
|
280
|
+
Amount of the injected species (source strength) --
|
|
281
|
+
i.e. interpreation of this number depends on `source_type`
|
|
282
|
+
"""
|
|
283
|
+
if self._scenario_sim.f_msx_in is None:
|
|
284
|
+
raise RuntimeError("You are not running EPANET-MSX")
|
|
285
|
+
|
|
286
|
+
source_type_ = "None"
|
|
287
|
+
if source_type == ToolkitConstants.EN_CONCEN:
|
|
288
|
+
source_type_ = "CONCEN"
|
|
289
|
+
elif source_type == ToolkitConstants.EN_MASS:
|
|
290
|
+
source_type_ = "MASS"
|
|
291
|
+
elif source_type == ToolkitConstants.EN_SETPOINT:
|
|
292
|
+
source_type_ = "SETPOINT"
|
|
293
|
+
elif source_type == ToolkitConstants.EN_FLOWPACED:
|
|
294
|
+
source_type_ = "FLOWPACED"
|
|
295
|
+
|
|
296
|
+
self._scenario_sim.epanet_api.setMSXPattern(pattern_id, [1])
|
|
297
|
+
self._scenario_sim.epanet_api.setMSXSources(node_id, species_id, source_type_,
|
|
298
|
+
source_strength, pattern_id)
|
|
299
|
+
|
|
181
300
|
@abstractmethod
|
|
182
301
|
def step(self, *actions) -> Union[tuple[ScadaData, float, bool], tuple[ScadaData, float]]:
|
|
183
302
|
"""
|
|
@@ -47,6 +47,7 @@ NETWORK_TOPOLOGY_ID = 26
|
|
|
47
47
|
PUMP_STATE_EVENT_ID = 28
|
|
48
48
|
PUMP_SPEED_EVENT_ID = 29
|
|
49
49
|
VALVE_STATE_EVENT_ID = 30
|
|
50
|
+
SPECIESINJECTION_EVENT_ID = 31
|
|
50
51
|
|
|
51
52
|
|
|
52
53
|
def my_packb(data: Any) -> bytes:
|
|
@@ -452,9 +453,15 @@ def save_to_file(f_out: str, data: Any, use_compression: bool = True) -> None:
|
|
|
452
453
|
def __encode_bsr_array(array: scipy.sparse.bsr_array
|
|
453
454
|
) -> tuple[tuple[int, int], tuple[list[float], tuple[list[int], list[int]]]]:
|
|
454
455
|
shape = array.shape
|
|
455
|
-
data =
|
|
456
|
-
rows =
|
|
457
|
-
cols =
|
|
456
|
+
data = []
|
|
457
|
+
rows = []
|
|
458
|
+
cols = []
|
|
459
|
+
|
|
460
|
+
array_ = array.tocsr() # Bug workaround: BSR arrays do not implement __getitem__
|
|
461
|
+
for i, j in zip(*array_.nonzero()):
|
|
462
|
+
rows.append(int(i))
|
|
463
|
+
cols.append(int(j))
|
|
464
|
+
data.append(float(array_[i, j]))
|
|
458
465
|
|
|
459
466
|
return shape, (data, (rows, cols))
|
|
460
467
|
|