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.
- epyt_flow/EPANET/compile_linux.sh +4 -0
- epyt_flow/EPANET/compile_macos.sh +4 -0
- epyt_flow/VERSION +1 -1
- epyt_flow/__init__.py +29 -18
- epyt_flow/data/benchmarks/leakdb.py +7 -12
- epyt_flow/data/networks.py +404 -40
- epyt_flow/rest_api/base_handler.py +14 -0
- epyt_flow/rest_api/scada_data/__init__.py +0 -0
- epyt_flow/rest_api/{scada_data_handler.py → scada_data/data_handlers.py} +3 -162
- epyt_flow/rest_api/scada_data/export_handlers.py +140 -0
- epyt_flow/rest_api/scada_data/handlers.py +209 -0
- epyt_flow/rest_api/scenario/__init__.py +0 -0
- epyt_flow/rest_api/scenario/event_handlers.py +118 -0
- epyt_flow/rest_api/{scenario_handler.py → scenario/handlers.py} +86 -67
- epyt_flow/rest_api/scenario/simulation_handlers.py +174 -0
- epyt_flow/rest_api/scenario/uncertainty_handlers.py +118 -0
- epyt_flow/rest_api/server.py +61 -24
- epyt_flow/simulation/events/leakages.py +27 -17
- epyt_flow/simulation/scada/scada_data.py +545 -14
- epyt_flow/simulation/scada/scada_data_export.py +39 -12
- epyt_flow/simulation/scenario_config.py +14 -20
- epyt_flow/simulation/scenario_simulator.py +358 -114
- epyt_flow/simulation/sensor_config.py +693 -37
- epyt_flow/topology.py +149 -8
- epyt_flow/utils.py +75 -18
- {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/METADATA +33 -5
- {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/RECORD +30 -22
- epyt_flow/EPANET/compile.sh +0 -4
- {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/LICENSE +0 -0
- {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/WHEEL +0 -0
- {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/top_level.txt +0 -0
epyt_flow/rest_api/server.py
CHANGED
|
@@ -4,15 +4,24 @@ This module provides the EPyT-Flow REST API server.
|
|
|
4
4
|
from wsgiref.simple_server import make_server, WSGIServer
|
|
5
5
|
import falcon
|
|
6
6
|
|
|
7
|
-
from .
|
|
8
|
-
ScenarioGeneralParamsHandler, ScenarioSensorConfigHandler,
|
|
9
|
-
ScenarioTopologyHandler, ScenarioConfigHandler,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
from .scenario.handlers import ScenarioManager, ScenarioNewHandler, \
|
|
8
|
+
ScenarioRemoveHandler, ScenarioGeneralParamsHandler, ScenarioSensorConfigHandler, \
|
|
9
|
+
ScenarioExportHandler, ScenarioTopologyHandler, ScenarioConfigHandler, \
|
|
10
|
+
ScenarioNodeDemandPatternHandler
|
|
11
|
+
from .scenario.uncertainty_handlers import ScenarioModelUncertaintyHandler, \
|
|
12
|
+
ScenarioSensorUncertaintyHandler
|
|
13
|
+
from .scenario.event_handlers import ScenarioLeakageHandler, ScenarioSensorFaultHandler
|
|
14
|
+
from .scenario.simulation_handlers import ScenarioSimulationHandler, \
|
|
15
|
+
ScenarioBasicQualitySimulationHandler, ScenarioAdvancedQualitySimulationHandler
|
|
16
|
+
from .scada_data.handlers import ScadaDataManager, ScadaDataSensorConfigHandler, \
|
|
17
|
+
ScadaDataRemoveHandler, ScadaDataSensorFaultsHandler, ScadaDataConvertUnitsHandler
|
|
18
|
+
from .scada_data.data_handlers import ScadaDataPressuresHandler, ScadaDataDemandsHandler, \
|
|
19
|
+
ScadaDataFlowsHandler, ScadaDataLinksQualityHandler, ScadaDataNodesQualityHandler, \
|
|
20
|
+
ScadaDataNodeBulkSpeciesHandler, ScadaDataLinkBulkSpeciesHandler, \
|
|
21
|
+
ScadaDataSurfaceSpeciesHandler, ScadaDataTankVolumesHandler, ScadaDataPumpStatesHandler, \
|
|
22
|
+
ScadaDataValveStatesHandler
|
|
23
|
+
from .scada_data.export_handlers import ScadaDataExportHandler, ScadaDataXlsxExportHandler, \
|
|
24
|
+
ScadaDataMatlabExportHandler, ScadaDataNumpyExportHandler
|
|
16
25
|
|
|
17
26
|
|
|
18
27
|
class RestApiService():
|
|
@@ -37,6 +46,8 @@ class RestApiService():
|
|
|
37
46
|
ScenarioNewHandler(self.scenario_mgr))
|
|
38
47
|
self.app.add_route("/scenario/{scenario_id}",
|
|
39
48
|
ScenarioRemoveHandler(self.scenario_mgr))
|
|
49
|
+
self.app.add_route("/scenario/{scenario_id}/export",
|
|
50
|
+
ScenarioExportHandler(self.scenario_mgr))
|
|
40
51
|
self.app.add_route("/scenario/{scenario_id}/topology",
|
|
41
52
|
ScenarioTopologyHandler(self.scenario_mgr))
|
|
42
53
|
self.app.add_route("/scenario/{scenario_id}/scenario_config",
|
|
@@ -45,11 +56,27 @@ class RestApiService():
|
|
|
45
56
|
ScenarioGeneralParamsHandler(self.scenario_mgr))
|
|
46
57
|
self.app.add_route("/scenario/{scenario_id}/sensor_config",
|
|
47
58
|
ScenarioSensorConfigHandler(self.scenario_mgr))
|
|
48
|
-
self.app.add_route("/scenario/{scenario_id}/
|
|
59
|
+
self.app.add_route("/scenario/{scenario_id}/uncertainty/model",
|
|
60
|
+
ScenarioModelUncertaintyHandler(self.scenario_mgr))
|
|
61
|
+
self.app.add_route("/scenario/{scenario_id}/uncertainty/sensors",
|
|
62
|
+
ScenarioSensorUncertaintyHandler(self.scenario_mgr))
|
|
63
|
+
self.app.add_route("/scenario/{scenario_id}/events/leakages",
|
|
49
64
|
ScenarioLeakageHandler(self.scenario_mgr))
|
|
65
|
+
self.app.add_route("/scenario/{scenario_id}/events/sensor_faults",
|
|
66
|
+
ScenarioSensorFaultHandler(self.scenario_mgr))
|
|
67
|
+
self.app.add_route("/scenario/{scenario_id}/node/{node_id}/demand_pattern",
|
|
68
|
+
ScenarioNodeDemandPatternHandler(self.scenario_mgr))
|
|
50
69
|
self.app.add_route("/scenario/{scenario_id}/simulation",
|
|
51
70
|
ScenarioSimulationHandler(scenario_mgr=self.scenario_mgr,
|
|
52
71
|
scada_data_mgr=self.scada_data_mgr))
|
|
72
|
+
self.app.add_route("/scenario/{scenario_id}/simulation/advanced_quality",
|
|
73
|
+
ScenarioBasicQualitySimulationHandler(scenario_mgr=self.scenario_mgr,
|
|
74
|
+
scada_data_mgr=
|
|
75
|
+
self.scada_data_mgr))
|
|
76
|
+
self.app.add_route("/scenario/{scenario_id}/simulation/basic_quality",
|
|
77
|
+
ScenarioAdvancedQualitySimulationHandler(scenario_mgr=self.scenario_mgr,
|
|
78
|
+
scada_data_mgr=
|
|
79
|
+
self.scada_data_mgr))
|
|
53
80
|
|
|
54
81
|
self.app.add_route("/scada_data/{data_id}",
|
|
55
82
|
ScadaDataRemoveHandler(self.scada_data_mgr))
|
|
@@ -57,28 +84,38 @@ class RestApiService():
|
|
|
57
84
|
ScadaDataSensorConfigHandler(self.scada_data_mgr))
|
|
58
85
|
self.app.add_route("/scada_data/{data_id}/sensor_faults",
|
|
59
86
|
ScadaDataSensorFaultsHandler(self.scada_data_mgr))
|
|
60
|
-
self.app.add_route("/scada_data/{data_id}/pressures",
|
|
87
|
+
self.app.add_route("/scada_data/{data_id}/nodes/pressures",
|
|
61
88
|
ScadaDataPressuresHandler(self.scada_data_mgr))
|
|
62
|
-
self.app.add_route("/scada_data/{data_id}/
|
|
63
|
-
ScadaDataFlowsHandler(self.scada_data_mgr))
|
|
64
|
-
self.app.add_route("/scada_data/{data_id}/demands",
|
|
89
|
+
self.app.add_route("/scada_data/{data_id}/nodes/demands",
|
|
65
90
|
ScadaDataDemandsHandler(self.scada_data_mgr))
|
|
91
|
+
self.app.add_route("/scada_data/{data_id}/nodes/quality",
|
|
92
|
+
ScadaDataNodesQualityHandler(self.scada_data_mgr))
|
|
93
|
+
self.app.add_route("/scada_data/{data_id}/nodes/bulk_species",
|
|
94
|
+
ScadaDataNodeBulkSpeciesHandler(self.scada_data_mgr))
|
|
95
|
+
self.app.add_route("/scada_data/{data_id}/links/flows",
|
|
96
|
+
ScadaDataFlowsHandler(self.scada_data_mgr))
|
|
97
|
+
self.app.add_route("/scada_data/{data_id}/links/quality",
|
|
98
|
+
ScadaDataLinksQualityHandler(self.scada_data_mgr))
|
|
99
|
+
self.app.add_route("/scada_data/{data_id}/links/bulk_species",
|
|
100
|
+
ScadaDataLinkBulkSpeciesHandler(self.scada_data_mgr))
|
|
101
|
+
self.app.add_route("/scada_data/{data_id}/links/surface_species",
|
|
102
|
+
ScadaDataSurfaceSpeciesHandler(self.scada_data_mgr))
|
|
66
103
|
self.app.add_route("/scada_data/{data_id}/pump_states",
|
|
67
104
|
ScadaDataPumpStatesHandler(self.scada_data_mgr))
|
|
68
105
|
self.app.add_route("/scada_data/{data_id}/valve_states",
|
|
69
106
|
ScadaDataValveStatesHandler(self.scada_data_mgr))
|
|
70
107
|
self.app.add_route("/scada_data/{data_id}/tank_volumes",
|
|
71
108
|
ScadaDataTankVolumesHandler(self.scada_data_mgr))
|
|
72
|
-
self.app.add_route("/scada_data/{data_id}/
|
|
73
|
-
|
|
74
|
-
self.app.add_route("/scada_data/{data_id}/
|
|
75
|
-
|
|
76
|
-
self.app.add_route("/scada_data/{data_id}/
|
|
77
|
-
|
|
78
|
-
self.app.add_route("/scada_data/{data_id}/
|
|
79
|
-
|
|
80
|
-
self.app.add_route("/scada_data/{data_id}/
|
|
81
|
-
|
|
109
|
+
self.app.add_route("/scada_data/{data_id}/export/xlsx",
|
|
110
|
+
ScadaDataXlsxExportHandler(scada_data_mgr=self.scada_data_mgr))
|
|
111
|
+
self.app.add_route("/scada_data/{data_id}/export/matlab",
|
|
112
|
+
ScadaDataMatlabExportHandler(scada_data_mgr=self.scada_data_mgr))
|
|
113
|
+
self.app.add_route("/scada_data/{data_id}/export/numpy",
|
|
114
|
+
ScadaDataNumpyExportHandler(scada_data_mgr=self.scada_data_mgr))
|
|
115
|
+
self.app.add_route("/scada_data/{data_id}/export",
|
|
116
|
+
ScadaDataExportHandler(scada_data_mgr=self.scada_data_mgr))
|
|
117
|
+
self.app.add_route("/scada_data/{data_id}/convert_units",
|
|
118
|
+
ScadaDataConvertUnitsHandler(scada_data_mgr=self.scada_data_mgr))
|
|
82
119
|
|
|
83
120
|
@property
|
|
84
121
|
def port(self) -> int:
|
|
@@ -5,6 +5,7 @@ from copy import deepcopy
|
|
|
5
5
|
import math
|
|
6
6
|
import numpy as np
|
|
7
7
|
import epyt
|
|
8
|
+
from epyt.epanet import ToolkitConstants
|
|
8
9
|
|
|
9
10
|
from .system_event import SystemEvent
|
|
10
11
|
from ...serialization import serializable, JsonSerializable, \
|
|
@@ -23,14 +24,14 @@ class Leakage(SystemEvent, JsonSerializable):
|
|
|
23
24
|
Note that if the leak is placed at a node, then 'link_id' must be None and the
|
|
24
25
|
ID of the node must be set in 'node_id'
|
|
25
26
|
diameter : `float`, optional
|
|
26
|
-
Diameter of this leak.
|
|
27
|
+
Diameter of this leak in either *foot* or *meter* (depending on the used flow units).
|
|
27
28
|
|
|
28
29
|
Alternatively, 'area' can be used for specifying the size of this leakage --
|
|
29
30
|
in this case, 'diameter' must be set to 'None'.
|
|
30
31
|
|
|
31
32
|
The default is None.
|
|
32
33
|
area : `float`, optional
|
|
33
|
-
Area of this leak.
|
|
34
|
+
Area of this leak in either *foot^2* or *meter^2* (depending on the used flow units).
|
|
34
35
|
|
|
35
36
|
Alternatively, 'diameter' can be used for specifying the size of this leakage --
|
|
36
37
|
in this case, 'area' must be set to 'None'.
|
|
@@ -124,19 +125,21 @@ class Leakage(SystemEvent, JsonSerializable):
|
|
|
124
125
|
@property
|
|
125
126
|
def diameter(self) -> float:
|
|
126
127
|
"""
|
|
127
|
-
Gets the diameter of the leak
|
|
128
|
+
Gets the diameter of the leak in either *foot* or *meter*
|
|
129
|
+
(depending on the sued flow units).
|
|
128
130
|
|
|
129
131
|
Returns
|
|
130
132
|
-------
|
|
131
133
|
`float`
|
|
132
|
-
Diameter of the leak.
|
|
134
|
+
Diameter (*foot* or *meter*) of the leak.
|
|
133
135
|
"""
|
|
134
136
|
return self.__diameter
|
|
135
137
|
|
|
136
138
|
@property
|
|
137
139
|
def area(self) -> float:
|
|
138
140
|
"""
|
|
139
|
-
Gets the area of the leak
|
|
141
|
+
Gets the area of the leak in either *foot^2* or *meter^2*
|
|
142
|
+
(depending on the sued flow units).
|
|
140
143
|
|
|
141
144
|
Returns
|
|
142
145
|
-------
|
|
@@ -190,46 +193,53 @@ class Leakage(SystemEvent, JsonSerializable):
|
|
|
190
193
|
"""
|
|
191
194
|
Computes the leak area given the diameter.
|
|
192
195
|
|
|
196
|
+
leak_area = pi * (diameter * .5)^2
|
|
197
|
+
|
|
193
198
|
Parameters
|
|
194
199
|
----------
|
|
195
200
|
diameter : `float`
|
|
196
|
-
Diameter (
|
|
201
|
+
Diameter (*foot* or *meter*) of the leak.
|
|
197
202
|
|
|
198
203
|
Returns
|
|
199
204
|
-------
|
|
200
205
|
`float`
|
|
201
|
-
Leak area in
|
|
206
|
+
Leak area in *foot^2* or *meter^2*.
|
|
202
207
|
"""
|
|
203
|
-
return
|
|
208
|
+
return np.pi * (diameter / 2) ** 2
|
|
204
209
|
|
|
205
|
-
def compute_leak_emitter_coefficient(self, area: float, discharge_coef: float = .75
|
|
206
|
-
g: float = 9.80665) -> float:
|
|
210
|
+
def compute_leak_emitter_coefficient(self, area: float, discharge_coef: float = .75) -> float:
|
|
207
211
|
"""
|
|
208
212
|
Computes the leak emitter coefficient.
|
|
209
213
|
|
|
210
|
-
emitter_coef = discharge_coef * area * sqrt(2*g)
|
|
214
|
+
emitter_coef = discharge_coef * area * sqrt(2*g)
|
|
215
|
+
where g is the gravitational constant, and discharge_coef = .75
|
|
211
216
|
|
|
212
217
|
leak_demand = emitter_coef * pressure^alpha where alpha = .5
|
|
213
218
|
|
|
214
219
|
Parameters
|
|
215
220
|
----------
|
|
216
221
|
area : `float`
|
|
217
|
-
Leak area (
|
|
218
|
-
:func
|
|
222
|
+
Leak area (foot^2 or meter^2) as computed in
|
|
223
|
+
:func:`~epyt_flow.simulation.events.leakages.Leakage.compute_leak_area`.
|
|
219
224
|
discharge_coef : `float`, optional
|
|
220
225
|
Discharge coefficient.
|
|
221
226
|
|
|
222
227
|
The default is set to 0.75
|
|
223
|
-
g : `float`, optional
|
|
224
|
-
Gravitational constant. Do not change this!
|
|
225
|
-
|
|
226
|
-
The default is 9.8
|
|
227
228
|
|
|
228
229
|
Returns
|
|
229
230
|
-------
|
|
230
231
|
`float`
|
|
231
232
|
Leak emitter coefficient.
|
|
232
233
|
"""
|
|
234
|
+
flow_unit = self._epanet_api.api.ENgetflowunits()
|
|
235
|
+
if flow_unit == ToolkitConstants.EN_CMH:
|
|
236
|
+
g = 127137600 # m/h^2
|
|
237
|
+
elif flow_unit == ToolkitConstants.EN_CFS:
|
|
238
|
+
g = 32.17405 # feet/s^2
|
|
239
|
+
else:
|
|
240
|
+
raise ValueError("Leakages are only implemented for the following flow units:\n" +
|
|
241
|
+
" EN_CMH (cubic foot/sec)\n EN_CFS (cubic meter/hr)")
|
|
242
|
+
|
|
233
243
|
return discharge_coef * area * np.sqrt(2. * g)
|
|
234
244
|
|
|
235
245
|
def init(self, epanet_api: epyt.epanet) -> None:
|