epyt-flow 0.1.1__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. epyt_flow/EPANET/compile_linux.sh +4 -0
  2. epyt_flow/EPANET/compile_macos.sh +4 -0
  3. epyt_flow/VERSION +1 -1
  4. epyt_flow/__init__.py +29 -18
  5. epyt_flow/data/benchmarks/leakdb.py +7 -12
  6. epyt_flow/data/networks.py +404 -40
  7. epyt_flow/rest_api/base_handler.py +14 -0
  8. epyt_flow/rest_api/scada_data/__init__.py +0 -0
  9. epyt_flow/rest_api/{scada_data_handler.py → scada_data/data_handlers.py} +3 -162
  10. epyt_flow/rest_api/scada_data/export_handlers.py +140 -0
  11. epyt_flow/rest_api/scada_data/handlers.py +209 -0
  12. epyt_flow/rest_api/scenario/__init__.py +0 -0
  13. epyt_flow/rest_api/scenario/event_handlers.py +118 -0
  14. epyt_flow/rest_api/{scenario_handler.py → scenario/handlers.py} +86 -67
  15. epyt_flow/rest_api/scenario/simulation_handlers.py +174 -0
  16. epyt_flow/rest_api/scenario/uncertainty_handlers.py +118 -0
  17. epyt_flow/rest_api/server.py +61 -24
  18. epyt_flow/simulation/events/leakages.py +27 -17
  19. epyt_flow/simulation/scada/scada_data.py +545 -14
  20. epyt_flow/simulation/scada/scada_data_export.py +39 -12
  21. epyt_flow/simulation/scenario_config.py +14 -20
  22. epyt_flow/simulation/scenario_simulator.py +358 -114
  23. epyt_flow/simulation/sensor_config.py +693 -37
  24. epyt_flow/topology.py +149 -8
  25. epyt_flow/utils.py +75 -18
  26. {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/METADATA +33 -5
  27. {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/RECORD +30 -22
  28. epyt_flow/EPANET/compile.sh +0 -4
  29. {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/LICENSE +0 -0
  30. {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/WHEEL +0 -0
  31. {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/top_level.txt +0 -0
epyt_flow/topology.py CHANGED
@@ -1,6 +1,9 @@
1
1
  """
2
2
  Module provides a class for representing the topology of WDN.
3
3
  """
4
+ from copy import deepcopy
5
+ import warnings
6
+ from typing import Any
4
7
  import numpy as np
5
8
  import networkx as nx
6
9
  from scipy.sparse import bsr_array
@@ -8,6 +11,39 @@ from scipy.sparse import bsr_array
8
11
  from .serialization import serializable, JsonSerializable, NETWORK_TOPOLOGY_ID
9
12
 
10
13
 
14
+ UNITS_USCUSTOM = 0
15
+ UNITS_SIMETRIC = 1
16
+
17
+
18
+ def unitscategoryid_to_str(unit_category_id: int) -> str:
19
+ """
20
+ Converts a given units category ID to the corresponding description.
21
+
22
+ Parameters
23
+ ----------
24
+ unit_category_id : `int`
25
+ ID of the units category.
26
+
27
+ Must be one of the following constants:
28
+
29
+ - UNITS_USCUSTOM = 0
30
+ - UNITS_SIMETRIC = 1
31
+
32
+ Returns
33
+ -------
34
+ `str`
35
+ Units category description.
36
+ """
37
+ if unit_category_id is None:
38
+ return ""
39
+ elif unit_category_id == UNITS_USCUSTOM:
40
+ return "US CUSTOMARY"
41
+ elif unit_category_id == UNITS_SIMETRIC:
42
+ return "SI METRIC"
43
+ else:
44
+ raise ValueError(f"Unknown units category ID '{unit_category_id}'")
45
+
46
+
11
47
  @serializable(NETWORK_TOPOLOGY_ID, ".epytflow_topology")
12
48
  class NetworkTopology(nx.Graph, JsonSerializable):
13
49
  """
@@ -22,13 +58,28 @@ class NetworkTopology(nx.Graph, JsonSerializable):
22
58
  links : `list[tuple[tuple[str, str], dict]]`
23
59
  List of all links/pipes -- i.e. link ID, ID of connecting nodes, and link information
24
60
  such as pipe diameter, length, etc.
61
+ units : `int`
62
+ Measurement units category -- i.e. US Customary or SI Metric.
63
+
64
+ Must be one of the following constants:
65
+
66
+ - UNITS_USCUSTOM = 0 (US Customary)
67
+ - UNITS_SIMETRIC = 1 (SI Metric)
25
68
  """
26
69
  def __init__(self, f_inp: str, nodes: list[tuple[str, dict]],
27
- links: list[tuple[str, tuple[str, str], dict]], **kwds):
70
+ links: list[tuple[str, tuple[str, str], dict]],
71
+ units: int = None,
72
+ **kwds):
28
73
  super().__init__(name=f_inp, **kwds)
29
74
 
30
75
  self.__nodes = nodes
31
76
  self.__links = links
77
+ self.__units = units
78
+
79
+ if units is None:
80
+ warnings.warn("Loading a file that was created with an outdated version of EPyT-Flow" +
81
+ " -- support of such old files will be removed in the next release!",
82
+ DeprecationWarning)
32
83
 
33
84
  for node_id, node_info in nodes:
34
85
  node_elevation = node_info["elevation"]
@@ -42,6 +93,76 @@ class NetworkTopology(nx.Graph, JsonSerializable):
42
93
  info={"id": link_id, "nodes": link, "diameter": link_diameter,
43
94
  "length": link_length})
44
95
 
96
+ def convert_units(self, units: int) -> Any:
97
+ """
98
+ Converts this instance to a :class:`epyt_flow.topology.NetworkTopology` instance
99
+ where everything is measured in given measurement units category
100
+ (US Customary or SI Metric).
101
+
102
+ Parameters
103
+ ----------
104
+ units : `int`
105
+ Measurement units category.
106
+
107
+ Must be one of the following constants:
108
+
109
+ - UNITS_USCUSTOM = 0 (US Customary)
110
+ - UNITS_SIMETRIC = 1 (SI Metric)
111
+
112
+ Returns
113
+ -------
114
+ :class:`epyt_flow.topology.NetworkTopology`
115
+ Network topology with the new measurements units.
116
+ """
117
+ if self.__units is None:
118
+ raise ValueError("This instance does not contain any units!")
119
+
120
+ if not isinstance(units, int):
121
+ raise TypeError(f"'units' must be an instance of 'int' but not of '{type(units)}'")
122
+ if units not in [UNITS_SIMETRIC, UNITS_USCUSTOM]:
123
+ raise ValueError(f"Invalid units '{units}'")
124
+
125
+ if units == self.__units:
126
+ warnings.warn("Units already set in this NetworkTopology instance -- nothing to do!")
127
+ return deepcopy(self)
128
+
129
+ # Get all data and convert units
130
+ inch_to_millimeter = 25.4
131
+ feet_to_meter = 0.3048
132
+
133
+ nodes = []
134
+ for node_id in self.get_all_nodes():
135
+ node_info = self.get_node_info(node_id)
136
+ if units == UNITS_USCUSTOM:
137
+ conv_factor = 1. / feet_to_meter
138
+ else:
139
+ conv_factor = feet_to_meter
140
+ node_info["elevation"] *= conv_factor
141
+ if "diameter" in node_info:
142
+ node_info["diameter"] *= conv_factor
143
+
144
+ nodes.append((node_id, node_info))
145
+
146
+ links = []
147
+ for link_id, link_nodes in self.get_all_links():
148
+ link_info = self.get_link_info(link_id)
149
+
150
+ if units == UNITS_USCUSTOM:
151
+ conv_factor = 1. / feet_to_meter
152
+ else:
153
+ conv_factor = feet_to_meter
154
+ link_info["length"] *= conv_factor
155
+
156
+ if units == UNITS_USCUSTOM:
157
+ conv_factor = 1. / inch_to_millimeter
158
+ else:
159
+ conv_factor = inch_to_millimeter
160
+ link_info["diameter"] *= conv_factor
161
+
162
+ links.append((link_id, link_nodes, link_info))
163
+
164
+ return NetworkTopology(f_inp=self.name, nodes=nodes, links=links, units=units)
165
+
45
166
  def get_all_nodes(self) -> list[str]:
46
167
  """
47
168
  Gets a list of all nodes.
@@ -64,7 +185,7 @@ class NetworkTopology(nx.Graph, JsonSerializable):
64
185
  """
65
186
  return [(link_id, end_points) for link_id, end_points, _ in self.__links]
66
187
 
67
- def get_node_info(self, node_id) -> dict:
188
+ def get_node_info(self, node_id: str) -> dict:
68
189
  """
69
190
  Gets all information (e.g. elevation, type, etc.) associated with a given node.
70
191
 
@@ -84,7 +205,7 @@ class NetworkTopology(nx.Graph, JsonSerializable):
84
205
 
85
206
  raise ValueError(f"Unknown node '{node_id}'")
86
207
 
87
- def get_link_info(self, link_id) -> dict:
208
+ def get_link_info(self, link_id: str) -> dict:
88
209
  """
89
210
  Gets all information (e.g. diameter, length, etc.) associated with a given link/pipe.
90
211
 
@@ -104,23 +225,43 @@ class NetworkTopology(nx.Graph, JsonSerializable):
104
225
 
105
226
  raise ValueError(f"Unknown link '{link_id}'")
106
227
 
228
+ @property
229
+ def units(self) -> int:
230
+ """
231
+ Gets the used measurement units category.
232
+
233
+ Will be one of the following constants:
234
+
235
+ - UNITS_USCUSTOM = 0 (US Customary)
236
+ - UNITS_SIMETRIC = 1 (SI Metric)
237
+
238
+ Returns
239
+ -------
240
+ `int`
241
+ Measurement units category.
242
+ """
243
+ return self.__units
244
+
107
245
  def __eq__(self, other) -> bool:
108
246
  if not isinstance(other, NetworkTopology):
109
247
  raise TypeError("Can not compare 'NetworkTopology' instance to " +
110
248
  f"'{type(other)}' instance")
111
249
 
112
250
  return super().__eq__(other) and \
113
- self.get_all_nodes() == other.get_all_nodes() and \
114
- all(link_a[0] == link_b[0] and all(link_a[1] == link_b[1])
115
- for link_a, link_b in zip(self.get_all_links(), other.get_all_links()))
251
+ self.get_all_nodes() == other.get_all_nodes() \
252
+ and all(link_a[0] == link_b[0] and all(link_a[1] == link_b[1])
253
+ for link_a, link_b in zip(self.get_all_links(), other.get_all_links())) \
254
+ and self.__units == other.units
116
255
 
117
256
  def __str__(self) -> str:
118
- return f"f_inp: {self.name} nodes: {self.__nodes} links: {self.__links}"
257
+ return f"f_inp: {self.name} nodes: {self.__nodes} links: {self.__links} " +\
258
+ f"units: {unitscategoryid_to_str(self.__units)}"
119
259
 
120
260
  def get_attributes(self) -> dict:
121
261
  return super().get_attributes() | {"f_inp": self.name,
122
262
  "nodes": self.__nodes,
123
- "links": self.__links}
263
+ "links": self.__links,
264
+ "units": self.__units}
124
265
 
125
266
  def get_adj_matrix(self) -> bsr_array:
126
267
  """
epyt_flow/utils.py CHANGED
@@ -9,6 +9,7 @@ from pathlib import Path
9
9
  import requests
10
10
  from tqdm import tqdm
11
11
  import numpy as np
12
+ import matplotlib
12
13
  import matplotlib.pyplot as plt
13
14
 
14
15
 
@@ -67,7 +68,8 @@ def volume_to_level(tank_volume: float, tank_diameter: float) -> float:
67
68
 
68
69
 
69
70
  def plot_timeseries_data(data: np.ndarray, labels: list[str] = None, x_axis_label: str = None,
70
- y_axis_label: str = None, show: bool = True) -> None:
71
+ y_axis_label: str = None, show: bool = True,
72
+ ax: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes:
71
73
  """
72
74
  Plots a single or multiple time series.
73
75
 
@@ -91,7 +93,18 @@ def plot_timeseries_data(data: np.ndarray, labels: list[str] = None, x_axis_labe
91
93
  show : `bool`, optional
92
94
  If True, the plot/figure is shown in a window.
93
95
 
96
+ Only considered when 'ax' is None.
97
+
94
98
  The default is True.
99
+ ax : `matplotlib.axes.Axes`, optional
100
+ If not None, 'ax' is used for plotting.
101
+
102
+ The default is None.
103
+
104
+ Returns
105
+ -------
106
+ `matplotlib.axes.Axes`
107
+ Plot.
95
108
  """
96
109
  if not isinstance(data, np.ndarray):
97
110
  raise TypeError(f"'data' must be an instance of 'numpy.ndarray' but not of '{type(data)}'")
@@ -111,28 +124,37 @@ def plot_timeseries_data(data: np.ndarray, labels: list[str] = None, x_axis_labe
111
124
  f"but not of '{type(y_axis_label)}'")
112
125
  if not isinstance(show, bool):
113
126
  raise TypeError(f"'show' must be an instance of 'bool' but not of '{type(show)}'")
127
+ if ax is not None:
128
+ if not isinstance(ax, matplotlib.axes.Axes):
129
+ raise TypeError("ax' must be an instance of 'matplotlib.axes.Axes'" +
130
+ f"but not of '{type(ax)}'")
114
131
 
115
- plt.figure()
132
+ fig = None
133
+ if ax is None:
134
+ fig, ax = plt.subplots()
116
135
 
117
136
  labels = labels if labels is not None else [None] * data.shape[0]
118
137
 
119
138
  for i in range(data.shape[0]):
120
- plt.plot(data[i, :], ".-", label=labels[i])
139
+ ax.plot(data[i, :], ".-", label=labels[i])
121
140
 
122
141
  if not any(label is None for label in labels):
123
- plt.legend()
142
+ ax.legend()
124
143
 
125
144
  if x_axis_label is not None:
126
- plt.xlabel(x_axis_label)
145
+ ax.set_xlabel(x_axis_label)
127
146
  if y_axis_label is not None:
128
- plt.ylabel(y_axis_label)
147
+ ax.set_ylabel(y_axis_label)
129
148
 
130
- if show is True:
149
+ if show is True and fig is not None:
131
150
  plt.show()
132
151
 
152
+ return ax
153
+
133
154
 
134
155
  def plot_timeseries_prediction(y: np.ndarray, y_pred: np.ndarray,
135
- confidence_interval: np.ndarray = None, show: bool = True) -> None:
156
+ confidence_interval: np.ndarray = None, show: bool = True,
157
+ ax: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes:
136
158
  """
137
159
  Plots the prediction (e.g. forecast) of *single* time series together with the
138
160
  ground truth time series. In addition, confidence intervals can be plotted as well.
@@ -151,7 +173,18 @@ def plot_timeseries_prediction(y: np.ndarray, y_pred: np.ndarray,
151
173
  show : `bool`, optional
152
174
  If True, the plot/figure is shown in a window.
153
175
 
176
+ Only considered when 'ax' is None.
177
+
154
178
  The default is True.
179
+ ax : `matplotlib.axes.Axes`, optional
180
+ If not None, 'axes' is used for plotting.
181
+
182
+ The default is None.
183
+
184
+ Returns
185
+ -------
186
+ `matplotlib.axes.Axes`
187
+ Plot.
155
188
  """
156
189
  if not isinstance(y_pred, np.ndarray):
157
190
  raise TypeError("'y_pred' must be an instance of 'numpy.ndarray' " +
@@ -167,21 +200,29 @@ def plot_timeseries_prediction(y: np.ndarray, y_pred: np.ndarray,
167
200
  raise ValueError("'y' must be a 1d array")
168
201
  if not isinstance(show, bool):
169
202
  raise TypeError(f"'show' must be an instance of 'bool' but not of '{type(show)}'")
203
+ if ax is not None:
204
+ if not isinstance(ax, matplotlib.axes.Axes):
205
+ raise TypeError("ax' must be an instance of 'matplotlib.axes.Axes'" +
206
+ f"but not of '{type(ax)}'")
170
207
 
171
- plt.figure()
208
+ fig = None
209
+ if ax is None:
210
+ fig, ax = plt.subplots()
172
211
 
173
212
  if confidence_interval is not None:
174
- plt.fill_between(range(len(y_pred)),
175
- y_pred - confidence_interval[0],
176
- y_pred + confidence_interval[1],
177
- alpha=0.5)
178
- plt.plot(y_pred, ".-", label="Prediction")
179
- plt.plot(y, ".-", label="Ground truth")
180
- plt.legend()
181
-
182
- if show is True:
213
+ ax.fill_between(range(len(y_pred)),
214
+ y_pred - confidence_interval[0],
215
+ y_pred + confidence_interval[1],
216
+ alpha=0.5)
217
+ ax.plot(y_pred, ".-", label="Prediction")
218
+ ax.plot(y, ".-", label="Ground truth")
219
+ ax.legend()
220
+
221
+ if show is True and fig is not None:
183
222
  plt.show()
184
223
 
224
+ return ax
225
+
185
226
 
186
227
  def download_if_necessary(download_path: str, url: str, verbose: bool = True) -> None:
187
228
  """
@@ -234,6 +275,22 @@ def create_path_if_not_exist(path_in: str) -> None:
234
275
  Path(path_in).mkdir(parents=True, exist_ok=True)
235
276
 
236
277
 
278
+ def pack_zip_archive(f_in: list[str], f_out: str) -> None:
279
+ """
280
+ Compresses a given list of files into a .zip archive.
281
+
282
+ Parameters
283
+ ----------
284
+ f_in : `list[str]`
285
+ List of files to be compressed into the .zip archive.
286
+ f_out : `str`
287
+ Path to the final .zip file.
288
+ """
289
+ with zipfile.ZipFile(f_out, "w") as f_zip_out:
290
+ for f_cur_in in f_in:
291
+ f_zip_out.write(f_cur_in, compress_type=zipfile.ZIP_DEFLATED)
292
+
293
+
237
294
  def unpack_zip_archive(f_in: str, folder_out: str) -> None:
238
295
  """
239
296
  Unpacks a .zip archive.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: epyt-flow
3
- Version: 0.1.1
3
+ Version: 0.3.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
@@ -32,8 +32,9 @@ Requires-Dist: falcon >=3.1.3
32
32
  Requires-Dist: multiprocess >=0.70.16
33
33
  Requires-Dist: psutil
34
34
 
35
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
36
35
  [![pypi](https://img.shields.io/pypi/v/epyt-flow.svg)](https://pypi.org/project/epyt-flow/)
36
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
37
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/epyt-flow)
37
38
  [![build](https://github.com/WaterFutures/EPyT-Flow/actions/workflows/build_tests.yml/badge.svg)](https://github.com/WaterFutures/EPyT-Flow/actions/workflows/build_tests.yml)
38
39
  [![Documentation Status](https://readthedocs.org/projects/epyt-flow/badge/?version=stable)](https://epyt-flow.readthedocs.io/en/stable/?badge=stable)
39
40
  [![Downloads](https://static.pepy.tech/badge/epyt-flow)](https://pepy.tech/project/epyt-flow)
@@ -41,6 +42,8 @@ Requires-Dist: psutil
41
42
 
42
43
  # EPyT-Flow -- EPANET Python Toolkit - Flow
43
44
 
45
+ <img src="https://github.com/WaterFutures/EPyT-Flow/blob/main/docs/_static/net1_plot.png?raw=true" align="right" height="230px"/>
46
+
44
47
  EPyT-Flow is a Python package building on top of [EPyT](https://github.com/OpenWaterAnalytics/EPyT)
45
48
  for providing easy access to water distribution network simulations.
46
49
  It aims to provide a high-level interface for the easy generation of hydraulic and water quality scenario data.
@@ -50,15 +53,40 @@ and [EPANET-MSX](https://github.com/USEPA/EPANETMSX/).
50
53
  EPyT-Flow provides easy access to popular benchmark data sets for event detection and localization.
51
54
  Furthermore, it also provides an environment for developing and testing control algorithms.
52
55
 
53
- ![](https://github.com/WaterFutures/EPyT-Flow/blob/main/docs/_static/net1_plot.png?raw=true)
56
+
57
+ ## Unique Features
58
+
59
+ Unique features of EPyT-Flow that make it superior to other (Python) toolboxes are the following:
60
+
61
+ - High-performance hydraulic and (advanced) water quality simulation
62
+ - High- and low-level interface
63
+ - Object-orientated design that is easy to extend and customize
64
+ - Sensor configurations
65
+ - Wide variety of pre-defined events (e.g. leakages, sensor faults, actuator events, cyber-attacks, etc.)
66
+ - Wide variety of pre-defined types of uncertainties (e.g. model uncertainties)
67
+ - Step-wise simulation and environment for training and evaluating control strategies
68
+ - Serialization module for easy exchange of data and (scenario) configurations
69
+ - REST API to make EPyT-Flow accessible in other applications
70
+ - Access to many WDNs and popular benchmarks (incl. their evaluation)
71
+
54
72
 
55
73
  ## Installation
56
74
 
57
75
  EPyT-Flow supports Python 3.9 - 3.12
58
76
 
59
77
  Note that [EPANET and EPANET-MSX sources](epyt_flow/EPANET/) are compiled and overwrite the binaries
60
- shipped by EPyT IF EPyT-Flow is installed on a Linux system. By this we not only aim to achieve
61
- a better performance of the simulations but also avoid any compatibility problems of pre-compiled binaries.
78
+ shipped by EPyT **IF** EPyT-Flow is installed on a Unix system and the *gcc* compiler is available.
79
+ By this, we not only aim to achieve a better performance of the simulations but also avoid any
80
+ compatibility issues of pre-compiled binaries.
81
+
82
+ #### Prerequisites for macOS users
83
+ The "true" *gcc* compiler (version 12) is needed which is not the
84
+ *clang* compiler that is shipped with Xcode and is linked to gcc!
85
+
86
+ The correct version of the "true" *gcc* can be installed via [brew](https://brew.sh/):
87
+ ```
88
+ brew install gcc@12
89
+ ```
62
90
 
63
91
  ### PyPI
64
92
 
@@ -1,10 +1,11 @@
1
- epyt_flow/VERSION,sha256=gERzFlKfxiAU-6oEf7Z8Uaww4ygwzaNwQFNJ2NZtGWw,6
2
- epyt_flow/__init__.py,sha256=NRznUeUdZWjqO7-gAD6gOEFUcve1-nYoFNuxTiGpkDM,1230
1
+ epyt_flow/VERSION,sha256=2RXMldbKj0euKXcT7UbU5cXZnd0p_Dxh4mO98wXytbA,6
2
+ epyt_flow/__init__.py,sha256=KNDiPWiHdB9a5ZF1ipjA1uoq61TwU2ThjaStpvSLBtY,1742
3
3
  epyt_flow/metrics.py,sha256=kvt42pzZrUR9PSlCyK4uq5kj6UlYHkt7OcCjLnI1RQE,12883
4
4
  epyt_flow/serialization.py,sha256=nBcwc3aMUbHF0zW8Nvpc49kKeLPh75blc3gzjKDR1ok,12893
5
- epyt_flow/topology.py,sha256=MwGH-qz5bulilXcT6u-Gyize38eLvYAOyOmqMG1ID3E,9795
6
- epyt_flow/utils.py,sha256=06hh8l-g-qQuhThWjAfrjKlr7S3MmFiK34kOnqM7ZsM,9817
7
- epyt_flow/EPANET/compile.sh,sha256=fA4Y5lYNr1pWKTbCkNa1rk_OOCd4_IJpLknOvlOoTYg,453
5
+ epyt_flow/topology.py,sha256=LTWqKwXVRfg3zYN16x5_ZH-wUj8U5hB2spLWzlEnsqM,14221
6
+ epyt_flow/utils.py,sha256=-1DFDpST_J86AB6pd2ufe_QQ06_tvQqB-5wD8DXacaU,11507
7
+ epyt_flow/EPANET/compile_linux.sh,sha256=wcrDyiB8NkivmaC-X9FI2WxhY3IJqDLiyIbVTv2XEPY,489
8
+ epyt_flow/EPANET/compile_macos.sh,sha256=1K33-bPdgr01EIf87YUvmOFHXyOkBWI6mKXQ8x1Hzmo,504
8
9
  epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS,sha256=yie5yAsEEPY0984PmkSRUdqEU9rVvRSGGWmjxdwCYMU,925
9
10
  epyt_flow/EPANET/EPANET/SRC_engines/LICENSE,sha256=8SIIcPPO-ga2HotvptcK3uRccZOEGCeUOIU0Asiq7CU,1070
10
11
  epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt,sha256=7LWHGbghkYJb18wkIskUzYswRq0ZTMu_m6nV0IfvCOs,1005
@@ -79,14 +80,14 @@ epyt_flow/EPANET/EPANET-MSX/Src/smatrix.h,sha256=heHTNgQNNDTs_Jx0YBts7_B7dPg8VUF
79
80
  epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx.h,sha256=L9y0VKHk5Fg1JZxID9uBzcvLZWOb1xuQP-MkmHH_LD4,3429
80
81
  epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx_export.h,sha256=h5UMaf6pH_0asRJOmhWUGAZhyA180ui2Cz8_y5h1FKw,1054
81
82
  epyt_flow/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
- epyt_flow/data/networks.py,sha256=E3tVEl63IKuXPPPtbfbhFto52R4-BRZgBqRYVzkDfcc,24343
83
+ epyt_flow/data/networks.py,sha256=Ct-3tNEJPq6EooGWHr_Hz4vkkNYjv-QgiSwNKOTZ-oM,38526
83
84
  epyt_flow/data/benchmarks/__init__.py,sha256=nJ6hqPaPNp8YMizniev3fwOWpzvvNUBMoRF16wACUkE,754
84
85
  epyt_flow/data/benchmarks/batadal.py,sha256=sa_OZwO5XIbJONgGMwgok-KCGyHq07WpIQagVq-a-gw,11175
85
86
  epyt_flow/data/benchmarks/batadal_data.py,sha256=oIzcysGivMPAgrfzrk5l8i-j6Ii96DPcFa6sL4TSaw8,880
86
87
  epyt_flow/data/benchmarks/battledim.py,sha256=K0j9tbfxuXJmqBQY_e5XBJZGDYavaOZ7efkCT96Fb8A,20167
87
88
  epyt_flow/data/benchmarks/battledim_data.py,sha256=0vHm-2eAiLv6U-n5dqUUWS1o_szFRy9mVJ3eqDRp4PE,3373
88
89
  epyt_flow/data/benchmarks/gecco_water_quality.py,sha256=1buZRJiNf4jsqWYg4Ud90GhqaiLVo4yij3RAZJkzsqE,10985
89
- epyt_flow/data/benchmarks/leakdb.py,sha256=aLDb_iRepAft2Wxu0BaUFD5LyoiRM5KvDv1dTIlm2QM,25445
90
+ epyt_flow/data/benchmarks/leakdb.py,sha256=jMMSxJ6XrjOo5b91sGwplT5mTcv3k9Xr-TnWz3BhMbw,24952
90
91
  epyt_flow/data/benchmarks/leakdb_data.py,sha256=FNssgMkC1wqWVlaOrrihr4Od9trEZY7KeK5KuBeRMvM,507058
91
92
  epyt_flow/data/benchmarks/water_usage.py,sha256=FLqjff3pha33oEU9ZM3UGPXn9eJJumsJH8Gdj7YFX3A,4778
92
93
  epyt_flow/gym/__init__.py,sha256=KNTDtPTEtHwZ4ehHfj9qGw81Z9acFqPIgMzYUzH5_uM,115
@@ -96,36 +97,43 @@ epyt_flow/models/__init__.py,sha256=be5s08y1Tg66SuNYKGz5GnNMHThnQJo8SWJdT9493Kc,
96
97
  epyt_flow/models/event_detector.py,sha256=idR7byBgloo07XEJEyMIwi49VW4wxJErLQtI-tJXWPs,789
97
98
  epyt_flow/models/sensor_interpolation_detector.py,sha256=5MBK9WlliGPonrNApf0j9lp-NjwF0iTwPDXx4yv7Fa0,3624
98
99
  epyt_flow/rest_api/__init__.py,sha256=4HilmXhdh6H56UHJBB2WUSULlEBUDnI1FPTP11ft3HE,126
99
- epyt_flow/rest_api/base_handler.py,sha256=Te70M40_oGCAE9zK2EdcUbQZQi7ti5_bGpxvublKvB0,1886
100
+ epyt_flow/rest_api/base_handler.py,sha256=I5ZcSiCJOH9sY5Ai_CdvSZ8PMVblyxCd82beE_2Sjlo,2262
100
101
  epyt_flow/rest_api/res_manager.py,sha256=j6-3FUBZNLKM9bCsIDZzSytfDYJbDLRwjn1mIPstTqI,2342
101
- epyt_flow/rest_api/scada_data_handler.py,sha256=hF1WZ1M8LUnULcaSIVh-F3qwEX4LNHX4FMOc3k_u4lU,16115
102
- epyt_flow/rest_api/scenario_handler.py,sha256=N6cBNWf9ehucVTzJOOr4yDL2QLJDZtI8jrfmhXmlJHM,11471
103
- epyt_flow/rest_api/server.py,sha256=C9fmVdA425hfLr-KuA1rIfC1XUy_McZ4CYs0P4gLha4,4928
102
+ epyt_flow/rest_api/server.py,sha256=kZlprvRw7op39s7KhtEt1TgAsqs94KTQEdzIW9NMMJc,7778
103
+ epyt_flow/rest_api/scada_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
104
+ epyt_flow/rest_api/scada_data/data_handlers.py,sha256=VpOQq_jb2d7CuZbPQ1lKfb5dd5UAkBp7H0mEtlDJMzo,10938
105
+ epyt_flow/rest_api/scada_data/export_handlers.py,sha256=m5gM1u7z-KFZ5SCSS0f2Fs6PpAT8FX3FvCS2mp7DmTA,4450
106
+ epyt_flow/rest_api/scada_data/handlers.py,sha256=tFVY11C3tolTkNVbXXBb0_KnHv38UE4fOUtnqkvec8Y,6893
107
+ epyt_flow/rest_api/scenario/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
108
+ epyt_flow/rest_api/scenario/event_handlers.py,sha256=oIqbXWQVqJp0MzE9V4UhGF4fXPF03oWbKEyLhC6g_Ko,3842
109
+ epyt_flow/rest_api/scenario/handlers.py,sha256=bDqMa-jM4hOMVqs0XvQJtHbQDZx9FP40GiEGwW38fGk,12353
110
+ epyt_flow/rest_api/scenario/simulation_handlers.py,sha256=oY1Ch6ZQgYT_5WeE1I7tvGqpDKlT664GHLdmcVKP7ek,5905
111
+ epyt_flow/rest_api/scenario/uncertainty_handlers.py,sha256=uuu6AP11ZZUp2P3Dnukjg5ZTjyYKljlubg1xLN1GnXY,4048
104
112
  epyt_flow/simulation/__init__.py,sha256=VGGJqJRUoXZjKJ0-m6KPp3JQqD_1TFW0pofLgkwZJ8M,164
105
113
  epyt_flow/simulation/parallel_simulation.py,sha256=mMevycgtnMjV2FDq50WS4HjAdcOlI72Aj6FBX4HZDtc,6508
106
- epyt_flow/simulation/scenario_config.py,sha256=vkAslXsnJIPZnaSDxe6gUhVuPUm58qwgXTkprmI4fq0,27168
107
- epyt_flow/simulation/scenario_simulator.py,sha256=ZDLRITDX7OK9Wdyw4SaPRpMx9j4Na3ghox3HjKAhTbM,81432
114
+ epyt_flow/simulation/scenario_config.py,sha256=6xZD3Gwje-isiSaoKCXLkX0R81SVDH8LojsXdDlH8to,26540
115
+ epyt_flow/simulation/scenario_simulator.py,sha256=Yf2oo3fMfvxrrW3nX8d6y2plrNcGZ-DBK-5mpLtplms,92070
108
116
  epyt_flow/simulation/scenario_visualizer.py,sha256=2gr1o731VLlhA8wQKgrLT94M43FsBNKjG_eucZPHy9A,2186
109
- epyt_flow/simulation/sensor_config.py,sha256=GZsyIBX6SpnW-VF4j2dol8vjwstY-Fi2WYofffQkU9c,58161
117
+ epyt_flow/simulation/sensor_config.py,sha256=9pUzvRm4HSF8zZ-Hu4pdpxzTjpNSdNmDvcPhRaRFNAI,80175
110
118
  epyt_flow/simulation/events/__init__.py,sha256=tIdqzs7_Cus4X2kbZG4Jl2zs-zsk_4rnajFOCvL0zlI,185
111
119
  epyt_flow/simulation/events/actuator_events.py,sha256=2_MPYbYO9As6fMkm5Oy9pjSB9kCvFuKpGu8ykYDAydg,7903
112
120
  epyt_flow/simulation/events/event.py,sha256=kARPV20XCAl6zxnJwI9U7ICtZUPACO_rgAmtHm1mGCs,2603
113
- epyt_flow/simulation/events/leakages.py,sha256=C-44uvk2mzbz9eaOg8ov1ZK-5rDK3P0kBYaul_LseYE,14569
121
+ epyt_flow/simulation/events/leakages.py,sha256=lDZNKOtVtQsKYhAuJ5Mt7tG6IfHX1436eSkjYTkQiZk,15267
114
122
  epyt_flow/simulation/events/sensor_faults.py,sha256=XX6k-GJh9RWZ4x54eGj9um-Ir9Eq41tY_9pRSCeYeqc,8447
115
123
  epyt_flow/simulation/events/sensor_reading_attack.py,sha256=bo5VavArN0wD5AHbIXJC9NFGZ7KR1uyWE6tBtwj0k9I,7538
116
124
  epyt_flow/simulation/events/sensor_reading_event.py,sha256=rQ-CmdpSUyZzDFYwNUGH2jGoj0oyU-aAb-7E8Oshhqw,6785
117
125
  epyt_flow/simulation/events/system_event.py,sha256=0KI2iaAaOyC9Y-FIfFVazeKT_4ORQRp26gWyMBUu_3c,2396
118
126
  epyt_flow/simulation/scada/__init__.py,sha256=ZFAxJVqwEVsgiyFilFetnb13gPhZg1JEOPWYvKIJT4c,90
119
127
  epyt_flow/simulation/scada/advanced_control.py,sha256=Enox02ggt36HdFLX7ZNxgxuqsTEeu9AACHrzU8CXGrg,4489
120
- epyt_flow/simulation/scada/scada_data.py,sha256=n0tNtVlOBFO7S5y4VvUrg37CD8ApiGsn1o4swnDQYtg,76694
121
- epyt_flow/simulation/scada/scada_data_export.py,sha256=zDWtDIpkKCwgVxj1FcAcsgXBVu3u5_KlElRaORQ9vJo,9860
128
+ epyt_flow/simulation/scada/scada_data.py,sha256=NfGDGrQ7HIXTcShUaGeCALTvGmM5LAJW0Bgmk0H4UQg,104867
129
+ epyt_flow/simulation/scada/scada_data_export.py,sha256=YlA-6R6XpQ28POyKsw1eEe23gMAuDFvwBuDUN-ciu2Y,11213
122
130
  epyt_flow/uncertainty/__init__.py,sha256=ZRjuJL9rDpWVSdPwObPxFpEmMTcgAl3VmPOsS6cIyGg,89
123
131
  epyt_flow/uncertainty/model_uncertainty.py,sha256=DAgyfvdTQvOVMyduuPIpPB_8e3GIMNpehu6kh0jFg0s,13592
124
132
  epyt_flow/uncertainty/sensor_noise.py,sha256=zJVULxnxVPSSqc6UW0iwZ9O-HGf9dn4CwScPqf4yCY0,2324
125
133
  epyt_flow/uncertainty/uncertainties.py,sha256=X-o7GZUC0HELtzpoXIAJaAeYOw35N05TuRoSmStcCpI,17669
126
134
  epyt_flow/uncertainty/utils.py,sha256=gq66c9-QMOxOqI6wgWLyFxjVV0fbG0_8Yzd6mQjNYNo,5315
127
- epyt_flow-0.1.1.dist-info/LICENSE,sha256=-4hYIY2BLmCkdOv2_PehEwlnMKTCes8_oyIUXjKtkug,1076
128
- epyt_flow-0.1.1.dist-info/METADATA,sha256=Blvpu5wFFXoip9AlclyKA7OfUjPzNGAe5UkEX53I7ag,5825
129
- epyt_flow-0.1.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
130
- epyt_flow-0.1.1.dist-info/top_level.txt,sha256=Wh_kd7TRL8ownCw3Y3dxx-9C0iTSk6wNauv_NX9JcrY,10
131
- epyt_flow-0.1.1.dist-info/RECORD,,
135
+ epyt_flow-0.3.0.dist-info/LICENSE,sha256=-4hYIY2BLmCkdOv2_PehEwlnMKTCes8_oyIUXjKtkug,1076
136
+ epyt_flow-0.3.0.dist-info/METADATA,sha256=tnq12BhftSSxemSI93ONtLRs4K4eT8R_I71NENxUuX4,7053
137
+ epyt_flow-0.3.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
138
+ epyt_flow-0.3.0.dist-info/top_level.txt,sha256=Wh_kd7TRL8ownCw3Y3dxx-9C0iTSk6wNauv_NX9JcrY,10
139
+ epyt_flow-0.3.0.dist-info/RECORD,,
@@ -1,4 +0,0 @@
1
- #!/bin/bash
2
- mkdir -p "../customlibs/"
3
- gcc -w -shared -Wl,-soname,libepanet2_2.so -fPIC -o "../customlibs/libepanet2_2.so" EPANET/SRC_engines/*.c -IEPANET/SRC_engines/include -lc -lm -pthread
4
- gcc -w -fPIC -shared -Wl,-soname,libepanetmsx2_2_0.so -o "../customlibs/libepanetmsx2_2_0.so" -fopenmp -Depanetmsx_EXPORTS -IEPANET-MSX/Src/include -IEPANET/SRC_engines/include EPANET-MSX/Src/*.c -Wl,-rpath=. "../customlibs/libepanet2_2.so" -lm -lgomp -lpthread