epyt-flow 0.9.0__tar.gz → 0.10.0__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.9.0 → epyt_flow-0.10.0}/LICENSE +1 -1
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/PKG-INFO +7 -6
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/README.md +3 -3
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/REQUIREMENTS.txt +1 -1
- epyt_flow-0.10.0/epyt_flow/VERSION +1 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/gym/scenario_control_env.py +9 -1
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/serialization.py +4 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/sensor_reading_attack.py +16 -3
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/sensor_reading_event.py +18 -3
- epyt_flow-0.10.0/epyt_flow/simulation/scada/__init__.py +5 -0
- epyt_flow-0.10.0/epyt_flow/simulation/scada/advanced_control.py +138 -0
- epyt_flow-0.10.0/epyt_flow/simulation/scada/complex_control.py +625 -0
- epyt_flow-0.9.0/epyt_flow/simulation/scada/advanced_control.py → epyt_flow-0.10.0/epyt_flow/simulation/scada/custom_control.py +3 -3
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/scada/scada_data.py +20 -3
- epyt_flow-0.10.0/epyt_flow/simulation/scada/simple_control.py +317 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/scenario_config.py +123 -23
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/scenario_simulator.py +394 -23
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/sensor_config.py +16 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow.egg-info/PKG-INFO +7 -6
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow.egg-info/SOURCES.txt +3 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow.egg-info/requires.txt +1 -1
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow.egg-info/top_level.txt +1 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/pyproject.toml +2 -1
- epyt_flow-0.9.0/epyt_flow/VERSION +0 -1
- epyt_flow-0.9.0/epyt_flow/simulation/scada/__init__.py +0 -3
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/CITATION.cff +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/CODE_OF_CONDUCT.md +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/MANIFEST.in +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/genmmd.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/hash.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/hash.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/input1.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/input2.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/input3.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/main.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/output.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/project.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/quality.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/report.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/rules.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/text.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/types.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/MSX_Updates.txt +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/dispersion.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/hash.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/hash.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx_export.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/mempool.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/mempool.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxchem.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxcompiler.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxdict.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxdispersion.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxerr.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxfile.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxinp.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxout.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxproj.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxqual.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxrpt.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxtank.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxtoolkit.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxtypes.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxutils.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxutils.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/newton.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/newton.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/rk5.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/rk5.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/ros2.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/ros2.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/smatrix.c +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/smatrix.h +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/readme.txt +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/compile_linux.sh +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/compile_macos.sh +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/__init__.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/__init__.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/__init__.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/batadal.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/batadal_data.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/battledim.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/battledim_data.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/gecco_water_quality.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/leakdb.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/leakdb_data.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/water_usage.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/networks.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/gym/__init__.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/gym/control_gyms.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/metrics.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/models/__init__.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/models/event_detector.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/models/sensor_interpolation_detector.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/__init__.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/base_handler.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/res_manager.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scada_data/__init__.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scada_data/data_handlers.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scada_data/export_handlers.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scada_data/handlers.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scenario/__init__.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scenario/event_handlers.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scenario/handlers.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scenario/simulation_handlers.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scenario/uncertainty_handlers.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/server.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/__init__.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/__init__.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/actuator_events.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/event.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/leakages.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/quality_events.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/sensor_faults.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/system_event.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/parallel_simulation.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/scada/scada_data_export.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/scenario_visualizer.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/topology.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/uncertainty/__init__.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/uncertainty/model_uncertainty.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/uncertainty/sensor_noise.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/uncertainty/uncertainties.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/uncertainty/utils.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/utils.py +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow.egg-info/dependency_links.txt +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/setup.cfg +0 -0
- {epyt_flow-0.9.0 → epyt_flow-0.10.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: epyt-flow
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
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
|
|
@@ -17,10 +17,11 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.10
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
21
|
Requires-Python: >=3.9
|
|
21
22
|
Description-Content-Type: text/markdown
|
|
22
23
|
License-File: LICENSE
|
|
23
|
-
Requires-Dist: epyt>=1.2.
|
|
24
|
+
Requires-Dist: epyt>=1.2.1
|
|
24
25
|
Requires-Dist: requests>=2.31.0
|
|
25
26
|
Requires-Dist: scipy>=1.11.4
|
|
26
27
|
Requires-Dist: u-msgpack-python>=2.8.0
|
|
@@ -66,8 +67,8 @@ Unique features of EPyT-Flow that make it superior to other (Python) toolboxes a
|
|
|
66
67
|
- High- and low-level interface
|
|
67
68
|
- Object-orientated design that is easy to extend and customize
|
|
68
69
|
- Sensor configurations
|
|
69
|
-
- Wide variety of pre-defined events (e.g. leakages, sensor faults, actuator events, cyber-attacks, etc.)
|
|
70
|
-
- Wide variety of pre-defined types of uncertainties (e.g. model uncertainties)
|
|
70
|
+
- Wide variety of pre-defined events (e.g. leakages, sensor faults, actuator events, contamination, cyber-attacks, etc.)
|
|
71
|
+
- Wide variety of pre-defined types of global & local uncertainties (e.g. model uncertainties)
|
|
71
72
|
- Step-wise simulation and environment for training and evaluating control strategies
|
|
72
73
|
- Serialization module for easy exchange of data and (scenario) configurations
|
|
73
74
|
- REST API to make EPyT-Flow accessible in other applications
|
|
@@ -76,7 +77,7 @@ Unique features of EPyT-Flow that make it superior to other (Python) toolboxes a
|
|
|
76
77
|
|
|
77
78
|
## Installation
|
|
78
79
|
|
|
79
|
-
EPyT-Flow supports Python 3.9 - 3.
|
|
80
|
+
EPyT-Flow supports Python 3.9 - 3.13
|
|
80
81
|
|
|
81
82
|
Note that [EPANET and EPANET-MSX sources](epyt_flow/EPANET/) are compiled and overwrite the binaries
|
|
82
83
|
shipped by EPyT **IF** EPyT-Flow is installed on a Unix system and the *gcc* compiler is available.
|
|
@@ -29,8 +29,8 @@ Unique features of EPyT-Flow that make it superior to other (Python) toolboxes a
|
|
|
29
29
|
- High- and low-level interface
|
|
30
30
|
- Object-orientated design that is easy to extend and customize
|
|
31
31
|
- Sensor configurations
|
|
32
|
-
- Wide variety of pre-defined events (e.g. leakages, sensor faults, actuator events, cyber-attacks, etc.)
|
|
33
|
-
- Wide variety of pre-defined types of uncertainties (e.g. model uncertainties)
|
|
32
|
+
- Wide variety of pre-defined events (e.g. leakages, sensor faults, actuator events, contamination, cyber-attacks, etc.)
|
|
33
|
+
- Wide variety of pre-defined types of global & local uncertainties (e.g. model uncertainties)
|
|
34
34
|
- Step-wise simulation and environment for training and evaluating control strategies
|
|
35
35
|
- Serialization module for easy exchange of data and (scenario) configurations
|
|
36
36
|
- REST API to make EPyT-Flow accessible in other applications
|
|
@@ -39,7 +39,7 @@ Unique features of EPyT-Flow that make it superior to other (Python) toolboxes a
|
|
|
39
39
|
|
|
40
40
|
## Installation
|
|
41
41
|
|
|
42
|
-
EPyT-Flow supports Python 3.9 - 3.
|
|
42
|
+
EPyT-Flow supports Python 3.9 - 3.13
|
|
43
43
|
|
|
44
44
|
Note that [EPANET and EPANET-MSX sources](epyt_flow/EPANET/) are compiled and overwrite the binaries
|
|
45
45
|
shipped by EPyT **IF** EPyT-Flow is installed on a Unix system and the *gcc* compiler is available.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.10.0
|
|
@@ -107,6 +107,14 @@ class ScenarioControlEnv(ABC):
|
|
|
107
107
|
Current SCADA data (i.e. sensor readings).
|
|
108
108
|
"""
|
|
109
109
|
if self._scenario_sim is not None:
|
|
110
|
+
# Abort current simulation if any is runing
|
|
111
|
+
try:
|
|
112
|
+
next(self._sim_generator)
|
|
113
|
+
self._sim_generator.send(True)
|
|
114
|
+
except StopIteration:
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
# Close scenario
|
|
110
118
|
self._scenario_sim.close()
|
|
111
119
|
|
|
112
120
|
self._scenario_sim = ScenarioSimulator(
|
|
@@ -194,7 +202,7 @@ class ScenarioControlEnv(ABC):
|
|
|
194
202
|
if pattern_idx == 0:
|
|
195
203
|
warnings.warn(f"No pattern for pump '{pump_id}' found -- a new pattern is created")
|
|
196
204
|
pattern_idx = self._scenario_sim.epanet_api.addPattern(f"pump_speed_{pump_id}")
|
|
197
|
-
self._scenario_sim.epanet_api.setLinkPumpPatternIndex(pump_idx, pattern_idx)
|
|
205
|
+
self._scenario_sim.epanet_api.setLinkPumpPatternIndex(pump_idx + 1, pattern_idx)
|
|
198
206
|
|
|
199
207
|
self._scenario_sim.epanet_api.setPattern(pattern_idx, np.array([speed]))
|
|
200
208
|
|
|
@@ -48,6 +48,10 @@ PUMP_STATE_EVENT_ID = 28
|
|
|
48
48
|
PUMP_SPEED_EVENT_ID = 29
|
|
49
49
|
VALVE_STATE_EVENT_ID = 30
|
|
50
50
|
SPECIESINJECTION_EVENT_ID = 31
|
|
51
|
+
SIMPLE_CONTROL_ID = 32
|
|
52
|
+
COMPLEX_CONTROL_ID = 33
|
|
53
|
+
COMPLEX_CONTROL_CONDITION_ID = 34
|
|
54
|
+
COMPLEX_CONTROL_ACTION_ID = 35
|
|
51
55
|
|
|
52
56
|
|
|
53
57
|
def my_packb(data: Any) -> bytes:
|
|
@@ -46,7 +46,7 @@ class SensorOverrideAttack(SensorReadingAttack, JsonSerializable):
|
|
|
46
46
|
@property
|
|
47
47
|
def new_sensor_values(self) -> np.ndarray:
|
|
48
48
|
"""
|
|
49
|
-
|
|
49
|
+
Returns the new sensor reading values -- i.e. these values replace the
|
|
50
50
|
true sensor reading values.
|
|
51
51
|
|
|
52
52
|
Returns
|
|
@@ -64,7 +64,7 @@ class SensorOverrideAttack(SensorReadingAttack, JsonSerializable):
|
|
|
64
64
|
raise TypeError("Can not compare 'SensorOverrideAttack' instance " +
|
|
65
65
|
f"with '{type(other)}' instance")
|
|
66
66
|
|
|
67
|
-
return super().__eq__(other) and self.__new_sensor_values == other.new_sensor_values
|
|
67
|
+
return super().__eq__(other) and np.all(self.__new_sensor_values == other.new_sensor_values)
|
|
68
68
|
|
|
69
69
|
def __str__(self) -> str:
|
|
70
70
|
return f"{type(self).__name__} {super().__str__()} " +\
|
|
@@ -151,6 +151,19 @@ class SensorReplayAttack(SensorReadingAttack, JsonSerializable):
|
|
|
151
151
|
"""
|
|
152
152
|
return self.__sensor_data_time_window_end
|
|
153
153
|
|
|
154
|
+
@property
|
|
155
|
+
def new_sensor_values(self) -> np.ndarray:
|
|
156
|
+
"""
|
|
157
|
+
Returns the new sensor reading values -- i.e. these values replace the
|
|
158
|
+
true sensor reading values.
|
|
159
|
+
|
|
160
|
+
Returns
|
|
161
|
+
-------
|
|
162
|
+
`np.ndarray`
|
|
163
|
+
New sensor readings.
|
|
164
|
+
"""
|
|
165
|
+
return deepcopy(self.__new_sensor_values)
|
|
166
|
+
|
|
154
167
|
def get_attributes(self) -> dict:
|
|
155
168
|
my_attributes = {"new_sensor_values": self.__new_sensor_values,
|
|
156
169
|
"replay_data_time_window_start": self.__sensor_data_time_window_start,
|
|
@@ -163,7 +176,7 @@ class SensorReplayAttack(SensorReadingAttack, JsonSerializable):
|
|
|
163
176
|
raise TypeError("Can not compare 'SensorReplayAttack' instance " +
|
|
164
177
|
f"with '{type(other)}' instance")
|
|
165
178
|
|
|
166
|
-
return super().__eq__(other) and self.__new_sensor_values == other.new_sensor_values
|
|
179
|
+
return super().__eq__(other) and np.all(self.__new_sensor_values == other.new_sensor_values)
|
|
167
180
|
|
|
168
181
|
def __str__(self) -> str:
|
|
169
182
|
return f"{type(self).__name__} {super().__str__()} " +\
|
|
@@ -95,13 +95,28 @@ class SensorReadingEvent(Event):
|
|
|
95
95
|
if self.__sensor_id not in sensor_config.tank_volume_sensors:
|
|
96
96
|
__show_warning()
|
|
97
97
|
elif self.__sensor_type == SENSOR_TYPE_NODE_BULK_SPECIES:
|
|
98
|
-
|
|
98
|
+
sensor_present = False
|
|
99
|
+
for _, sensors_id in sensor_config.bulk_species_node_sensors.items():
|
|
100
|
+
if self.__sensor_id in sensors_id:
|
|
101
|
+
sensor_present = True
|
|
102
|
+
break
|
|
103
|
+
if sensor_present is False:
|
|
99
104
|
__show_warning()
|
|
100
105
|
elif self.__sensor_type == SENSOR_TYPE_LINK_BULK_SPECIES:
|
|
101
|
-
|
|
106
|
+
sensor_present = False
|
|
107
|
+
for _, sensors_id in sensor_config.bulk_species_link_sensors.items():
|
|
108
|
+
if self.__sensor_id in sensors_id:
|
|
109
|
+
sensor_present = True
|
|
110
|
+
break
|
|
111
|
+
if sensor_present is False:
|
|
102
112
|
__show_warning()
|
|
103
113
|
elif self.__sensor_type == SENSOR_TYPE_SURFACE_SPECIES:
|
|
104
|
-
|
|
114
|
+
sensor_present = False
|
|
115
|
+
for _, sensors_id in sensor_config.surface_species_sensors.items():
|
|
116
|
+
if self.__sensor_id in sensors_id:
|
|
117
|
+
sensor_present = True
|
|
118
|
+
break
|
|
119
|
+
if sensor_present is False:
|
|
105
120
|
__show_warning()
|
|
106
121
|
|
|
107
122
|
@property
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Deprecated -- use epyt_flow.simulation.scada.custom_control instead
|
|
3
|
+
"""
|
|
4
|
+
import warnings
|
|
5
|
+
from abc import abstractmethod, ABC
|
|
6
|
+
import numpy as np
|
|
7
|
+
import epyt
|
|
8
|
+
|
|
9
|
+
from . import ScadaData
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
warnings.warn("'epyt_flow.simulation.scada.advanced_control' is deprecated and will be removed " +
|
|
13
|
+
"in future releases -- use 'epyt_flow.simulation.scada.custom_control' instead")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AdvancedControlModule(ABC):
|
|
17
|
+
"""
|
|
18
|
+
Base class for a control module.
|
|
19
|
+
|
|
20
|
+
Attributes
|
|
21
|
+
----------
|
|
22
|
+
epanet_api : `epyt.epanet <https://epanet-python-toolkit-epyt.readthedocs.io/en/latest/api.html#epyt.epanet.epanet>`_
|
|
23
|
+
API to EPANET and EPANET-MSX. Is set in :func:`init`.
|
|
24
|
+
"""
|
|
25
|
+
def __init__(self, **kwds):
|
|
26
|
+
self._epanet_api = None
|
|
27
|
+
|
|
28
|
+
super().__init__(**kwds)
|
|
29
|
+
|
|
30
|
+
def init(self, epanet_api: epyt.epanet) -> None:
|
|
31
|
+
"""
|
|
32
|
+
Initializes the control module.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
epanet_api : `epyt.epanet <https://epanet-python-toolkit-epyt.readthedocs.io/en/latest/api.html#epyt.epanet.epanet>`_
|
|
37
|
+
API to EPANET for implementing the control module.
|
|
38
|
+
"""
|
|
39
|
+
if not isinstance(epanet_api, epyt.epanet):
|
|
40
|
+
raise TypeError("'epanet_api' must be an instance of 'epyt.epanet' but not of " +
|
|
41
|
+
f"'{type(epanet_api)}'")
|
|
42
|
+
|
|
43
|
+
self._epanet_api = epanet_api
|
|
44
|
+
|
|
45
|
+
def set_pump_status(self, pump_id: str, status: int) -> None:
|
|
46
|
+
"""
|
|
47
|
+
Sets the status of a pump.
|
|
48
|
+
|
|
49
|
+
Parameters
|
|
50
|
+
----------
|
|
51
|
+
pump_id : `str`
|
|
52
|
+
ID of the pump for which the status is set.
|
|
53
|
+
status : `int`
|
|
54
|
+
New status of the pump -- either active (i.e. open) or inactive (i.e. closed).
|
|
55
|
+
|
|
56
|
+
Must be one of the following constants defined in
|
|
57
|
+
:class:`~epyt_flow.simulation.events.actuator_events.ActuatorConstants`:
|
|
58
|
+
|
|
59
|
+
- EN_CLOSED = 0
|
|
60
|
+
- EN_OPEN = 1
|
|
61
|
+
"""
|
|
62
|
+
pump_idx = self._epanet_api.getLinkPumpNameID().index(pump_id)
|
|
63
|
+
pump_link_idx = self._epanet_api.getLinkPumpIndex(pump_idx + 1)
|
|
64
|
+
self._epanet_api.setLinkStatus(pump_link_idx, status)
|
|
65
|
+
|
|
66
|
+
def set_pump_speed(self, pump_id: str, speed: float) -> None:
|
|
67
|
+
"""
|
|
68
|
+
Sets the speed of a pump.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
pump_id : `str`
|
|
73
|
+
ID of the pump for which the pump speed is set.
|
|
74
|
+
speed : `float`
|
|
75
|
+
New pump speed.
|
|
76
|
+
"""
|
|
77
|
+
pump_idx = self._epanet_api.getLinkPumpNameID().index(pump_id)
|
|
78
|
+
pattern_idx = self._epanet_api.getLinkPumpPatternIndex(pump_idx + 1)
|
|
79
|
+
|
|
80
|
+
if pattern_idx == 0:
|
|
81
|
+
warnings.warn(f"No pattern for pump '{pump_id}' found -- a new pattern is created")
|
|
82
|
+
pattern_idx = self._epanet_api.addPattern(f"pump_speed_{pump_id}")
|
|
83
|
+
self._epanet_api.setLinkPumpPatternIndex(pattern_idx)
|
|
84
|
+
|
|
85
|
+
self._epanet_api.setPattern(pattern_idx, np.array([speed]))
|
|
86
|
+
|
|
87
|
+
def set_valve_status(self, valve_id: str, status: int) -> None:
|
|
88
|
+
"""
|
|
89
|
+
Sets the status of a valve.
|
|
90
|
+
|
|
91
|
+
Parameters
|
|
92
|
+
----------
|
|
93
|
+
valve_id : `str`
|
|
94
|
+
ID of the valve for which the status is set.
|
|
95
|
+
status : `int`
|
|
96
|
+
New status of the valve -- either open or closed.
|
|
97
|
+
|
|
98
|
+
Must be one of the following constants defined in
|
|
99
|
+
:class:`~epyt_flow.simulation.events.actuator_events.ActuatorConstants`:
|
|
100
|
+
|
|
101
|
+
- EN_CLOSED = 0
|
|
102
|
+
- EN_OPEN = 1
|
|
103
|
+
"""
|
|
104
|
+
valve_idx = self._epanet_api.getLinkValveNameID().index(valve_id)
|
|
105
|
+
valve_link_idx = self._epanet_api.getLinkValveIndex()[valve_idx]
|
|
106
|
+
self._epanet_api.setLinkStatus(valve_link_idx, status)
|
|
107
|
+
|
|
108
|
+
def set_node_quality_source_value(self, node_id: str, pattern_id: str,
|
|
109
|
+
qual_value: float) -> None:
|
|
110
|
+
"""
|
|
111
|
+
Sets the quality source at a particular node to a specific value -- e.g.
|
|
112
|
+
setting the chlorine concentration injection to a specified value.
|
|
113
|
+
|
|
114
|
+
Parameters
|
|
115
|
+
----------
|
|
116
|
+
node_id : `str`
|
|
117
|
+
ID of the node.
|
|
118
|
+
pattern_id : `str`
|
|
119
|
+
ID of the quality pattern at the specific node.
|
|
120
|
+
qual_value : `float`
|
|
121
|
+
New quality source value.
|
|
122
|
+
"""
|
|
123
|
+
node_idx = self._epanet_api.getNodeIndex(node_id)
|
|
124
|
+
pattern_idx = self._epanet_api.getPatternIndex(pattern_id)
|
|
125
|
+
self._epanet_api.setNodeSourceQuality(node_idx, 1)
|
|
126
|
+
self._epanet_api.setPattern(pattern_idx, np.array([qual_value]))
|
|
127
|
+
|
|
128
|
+
@abstractmethod
|
|
129
|
+
def step(self, scada_data: ScadaData) -> None:
|
|
130
|
+
"""
|
|
131
|
+
Implements the control algorithm -- i.e. mapping of sensor reading to actions.
|
|
132
|
+
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
135
|
+
scada_data : :class:`~epyt_flow.simulation.scada.scada_data.ScadaData`
|
|
136
|
+
Sensor readings.
|
|
137
|
+
"""
|
|
138
|
+
raise NotImplementedError()
|