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.
Files changed (155) hide show
  1. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/LICENSE +1 -1
  2. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/PKG-INFO +7 -6
  3. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/README.md +3 -3
  4. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/REQUIREMENTS.txt +1 -1
  5. epyt_flow-0.10.0/epyt_flow/VERSION +1 -0
  6. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/gym/scenario_control_env.py +9 -1
  7. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/serialization.py +4 -0
  8. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/sensor_reading_attack.py +16 -3
  9. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/sensor_reading_event.py +18 -3
  10. epyt_flow-0.10.0/epyt_flow/simulation/scada/__init__.py +5 -0
  11. epyt_flow-0.10.0/epyt_flow/simulation/scada/advanced_control.py +138 -0
  12. epyt_flow-0.10.0/epyt_flow/simulation/scada/complex_control.py +625 -0
  13. 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
  14. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/scada/scada_data.py +20 -3
  15. epyt_flow-0.10.0/epyt_flow/simulation/scada/simple_control.py +317 -0
  16. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/scenario_config.py +123 -23
  17. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/scenario_simulator.py +394 -23
  18. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/sensor_config.py +16 -0
  19. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow.egg-info/PKG-INFO +7 -6
  20. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow.egg-info/SOURCES.txt +3 -0
  21. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow.egg-info/requires.txt +1 -1
  22. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow.egg-info/top_level.txt +1 -0
  23. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/pyproject.toml +2 -1
  24. epyt_flow-0.9.0/epyt_flow/VERSION +0 -1
  25. epyt_flow-0.9.0/epyt_flow/simulation/scada/__init__.py +0 -3
  26. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/CITATION.cff +0 -0
  27. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/CODE_OF_CONDUCT.md +0 -0
  28. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/MANIFEST.in +0 -0
  29. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +0 -0
  30. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +0 -0
  31. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +0 -0
  32. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +0 -0
  33. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +0 -0
  34. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +0 -0
  35. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +0 -0
  36. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +0 -0
  37. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +0 -0
  38. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/genmmd.c +0 -0
  39. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/hash.c +0 -0
  40. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/hash.h +0 -0
  41. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +0 -0
  42. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +0 -0
  43. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +0 -0
  44. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +0 -0
  45. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +0 -0
  46. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +0 -0
  47. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +0 -0
  48. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +0 -0
  49. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/input1.c +0 -0
  50. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/input2.c +0 -0
  51. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/input3.c +0 -0
  52. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/main.c +0 -0
  53. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +0 -0
  54. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +0 -0
  55. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/output.c +0 -0
  56. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/project.c +0 -0
  57. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/quality.c +0 -0
  58. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +0 -0
  59. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +0 -0
  60. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/report.c +0 -0
  61. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/rules.c +0 -0
  62. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +0 -0
  63. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/text.h +0 -0
  64. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET/SRC_engines/types.h +0 -0
  65. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/MSX_Updates.txt +0 -0
  66. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/dispersion.h +0 -0
  67. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/hash.c +0 -0
  68. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/hash.h +0 -0
  69. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx.h +0 -0
  70. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx_export.h +0 -0
  71. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.c +0 -0
  72. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.h +0 -0
  73. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/mempool.c +0 -0
  74. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/mempool.h +0 -0
  75. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxchem.c +0 -0
  76. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxcompiler.c +0 -0
  77. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxdict.h +0 -0
  78. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxdispersion.c +0 -0
  79. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxerr.c +0 -0
  80. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxfile.c +0 -0
  81. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.c +0 -0
  82. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.h +0 -0
  83. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxinp.c +0 -0
  84. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxout.c +0 -0
  85. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxproj.c +0 -0
  86. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxqual.c +0 -0
  87. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxrpt.c +0 -0
  88. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxtank.c +0 -0
  89. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxtoolkit.c +0 -0
  90. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxtypes.h +0 -0
  91. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxutils.c +0 -0
  92. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/msxutils.h +0 -0
  93. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/newton.c +0 -0
  94. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/newton.h +0 -0
  95. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/rk5.c +0 -0
  96. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/rk5.h +0 -0
  97. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/ros2.c +0 -0
  98. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/ros2.h +0 -0
  99. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/smatrix.c +0 -0
  100. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/Src/smatrix.h +0 -0
  101. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/EPANET-MSX/readme.txt +0 -0
  102. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/compile_linux.sh +0 -0
  103. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/EPANET/compile_macos.sh +0 -0
  104. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/__init__.py +0 -0
  105. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/__init__.py +0 -0
  106. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/__init__.py +0 -0
  107. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/batadal.py +0 -0
  108. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/batadal_data.py +0 -0
  109. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/battledim.py +0 -0
  110. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/battledim_data.py +0 -0
  111. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/gecco_water_quality.py +0 -0
  112. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/leakdb.py +0 -0
  113. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/leakdb_data.py +0 -0
  114. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/benchmarks/water_usage.py +0 -0
  115. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/data/networks.py +0 -0
  116. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/gym/__init__.py +0 -0
  117. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/gym/control_gyms.py +0 -0
  118. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/metrics.py +0 -0
  119. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/models/__init__.py +0 -0
  120. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/models/event_detector.py +0 -0
  121. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/models/sensor_interpolation_detector.py +0 -0
  122. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/__init__.py +0 -0
  123. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/base_handler.py +0 -0
  124. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/res_manager.py +0 -0
  125. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scada_data/__init__.py +0 -0
  126. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scada_data/data_handlers.py +0 -0
  127. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scada_data/export_handlers.py +0 -0
  128. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scada_data/handlers.py +0 -0
  129. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scenario/__init__.py +0 -0
  130. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scenario/event_handlers.py +0 -0
  131. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scenario/handlers.py +0 -0
  132. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scenario/simulation_handlers.py +0 -0
  133. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/scenario/uncertainty_handlers.py +0 -0
  134. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/rest_api/server.py +0 -0
  135. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/__init__.py +0 -0
  136. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/__init__.py +0 -0
  137. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/actuator_events.py +0 -0
  138. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/event.py +0 -0
  139. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/leakages.py +0 -0
  140. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/quality_events.py +0 -0
  141. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/sensor_faults.py +0 -0
  142. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/events/system_event.py +0 -0
  143. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/parallel_simulation.py +0 -0
  144. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/scada/scada_data_export.py +0 -0
  145. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/simulation/scenario_visualizer.py +0 -0
  146. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/topology.py +0 -0
  147. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/uncertainty/__init__.py +0 -0
  148. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/uncertainty/model_uncertainty.py +0 -0
  149. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/uncertainty/sensor_noise.py +0 -0
  150. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/uncertainty/uncertainties.py +0 -0
  151. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/uncertainty/utils.py +0 -0
  152. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow/utils.py +0 -0
  153. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/epyt_flow.egg-info/dependency_links.txt +0 -0
  154. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/setup.cfg +0 -0
  155. {epyt_flow-0.9.0 → epyt_flow-0.10.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 EPyT-Flow Developers
3
+ Copyright (c) EPyT-Flow Developers
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: epyt-flow
3
- Version: 0.9.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.0
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.12
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.12
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.
@@ -1,4 +1,4 @@
1
- epyt>=1.2.0
1
+ epyt>=1.2.1
2
2
  requests>=2.31.0
3
3
  scipy>=1.11.4
4
4
  u-msgpack-python>=2.8.0
@@ -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
- Get the new sensor reading values -- i.e. these values replace the
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
- if self.__sensor_id not in sensor_config.bulk_species_node_sensors:
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
- if self.__sensor_id not in sensor_config.bulk_species_link_sensors:
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
- if self.__sensor_id not in sensor_config.surface_species_sensors:
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,5 @@
1
+ from .scada_data import *
2
+ from .scada_data_export import *
3
+ from .custom_control import *
4
+ from .simple_control import *
5
+ from .complex_control import *
@@ -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()