epyt-flow 0.13.1__py3-none-any.whl → 0.14.1__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 (63) hide show
  1. epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +40 -8
  2. epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +3 -3
  3. epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +24 -7
  4. epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +726 -374
  5. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +128 -32
  6. epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +7 -1
  7. epyt_flow/EPANET/EPANET/SRC_engines/flowbalance.c +186 -0
  8. epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +40 -14
  9. epyt_flow/EPANET/EPANET/SRC_engines/hash.c +177 -177
  10. epyt_flow/EPANET/EPANET/SRC_engines/hash.h +28 -28
  11. epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +192 -40
  12. epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +101 -46
  13. epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +85 -24
  14. epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +29 -63
  15. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +70 -37
  16. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +408 -234
  17. epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +87 -37
  18. epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +153 -79
  19. epyt_flow/EPANET/EPANET/SRC_engines/input1.c +59 -94
  20. epyt_flow/EPANET/EPANET/SRC_engines/input2.c +73 -202
  21. epyt_flow/EPANET/EPANET/SRC_engines/input3.c +446 -351
  22. epyt_flow/EPANET/EPANET/SRC_engines/leakage.c +527 -0
  23. epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +8 -4
  24. epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +23 -23
  25. epyt_flow/EPANET/EPANET/SRC_engines/output.c +5 -4
  26. epyt_flow/EPANET/EPANET/SRC_engines/project.c +407 -75
  27. epyt_flow/EPANET/EPANET/SRC_engines/quality.c +12 -2
  28. epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +70 -13
  29. epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +7 -5
  30. epyt_flow/EPANET/EPANET/SRC_engines/report.c +88 -20
  31. epyt_flow/EPANET/EPANET/SRC_engines/rules.c +144 -6
  32. epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +19 -19
  33. epyt_flow/EPANET/EPANET/SRC_engines/text.h +16 -5
  34. epyt_flow/EPANET/EPANET/SRC_engines/types.h +73 -19
  35. epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.c +59 -0
  36. epyt_flow/EPANET/EPANET/SRC_engines/util/cstr_helper.h +38 -0
  37. epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.c +92 -0
  38. epyt_flow/EPANET/EPANET/SRC_engines/util/errormanager.h +39 -0
  39. epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.c +212 -0
  40. epyt_flow/EPANET/EPANET/SRC_engines/util/filemanager.h +81 -0
  41. epyt_flow/EPANET/EPANET/SRC_engines/validate.c +408 -0
  42. epyt_flow/EPANET/compile_linux.sh +1 -1
  43. epyt_flow/EPANET/compile_macos.sh +2 -2
  44. epyt_flow/VERSION +1 -1
  45. epyt_flow/__init__.py +1 -1
  46. epyt_flow/gym/scenario_control_env.py +26 -3
  47. epyt_flow/simulation/backend/my_epyt.py +58 -13
  48. epyt_flow/simulation/events/quality_events.py +6 -6
  49. epyt_flow/simulation/events/sensor_faults.py +24 -24
  50. epyt_flow/simulation/events/system_event.py +3 -3
  51. epyt_flow/simulation/scada/scada_data.py +10 -14
  52. epyt_flow/simulation/scenario_simulator.py +100 -20
  53. epyt_flow/topology.py +8 -1
  54. epyt_flow/uncertainty/model_uncertainty.py +292 -150
  55. epyt_flow/uncertainty/uncertainties.py +2 -2
  56. {epyt_flow-0.13.1.dist-info → epyt_flow-0.14.1.dist-info}/METADATA +4 -4
  57. {epyt_flow-0.13.1.dist-info → epyt_flow-0.14.1.dist-info}/RECORD +60 -54
  58. {epyt_flow-0.13.1.dist-info → epyt_flow-0.14.1.dist-info}/WHEEL +1 -1
  59. epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +0 -18
  60. epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +0 -131
  61. epyt_flow/EPANET/EPANET/SRC_engines/main.c +0 -93
  62. {epyt_flow-0.13.1.dist-info → epyt_flow-0.14.1.dist-info}/licenses/LICENSE +0 -0
  63. {epyt_flow-0.13.1.dist-info → epyt_flow-0.14.1.dist-info}/top_level.txt +0 -0
@@ -64,7 +64,7 @@ class SpeciesInjectionEvent(SystemEvent, JsonSerializable):
64
64
 
65
65
  self.__species_id = species_id
66
66
  self.__node_id = node_id
67
- self.__profile = profile
67
+ self._profile = profile
68
68
  self.__source_type = source_type
69
69
 
70
70
  super().__init__(**kwds)
@@ -103,7 +103,7 @@ class SpeciesInjectionEvent(SystemEvent, JsonSerializable):
103
103
  `numpy.ndarray`
104
104
  Pattern of the injection.
105
105
  """
106
- return deepcopy(self.__profile)
106
+ return deepcopy(self._profile)
107
107
 
108
108
  @property
109
109
  def source_type(self) -> int:
@@ -125,17 +125,17 @@ class SpeciesInjectionEvent(SystemEvent, JsonSerializable):
125
125
 
126
126
  def get_attributes(self) -> dict:
127
127
  return super().get_attributes() | {"species_id": self.__species_id,
128
- "node_id": self.__node_id, "profile": self.__profile,
128
+ "node_id": self.__node_id, "profile": self._profile,
129
129
  "source_type": self.__source_type}
130
130
 
131
131
  def __eq__(self, other) -> bool:
132
132
  return super().__eq__(other) and self.__species_id == other.species_id and \
133
- self.__node_id == other.node_id and np.all(self.__profile == other.profile) and \
133
+ self.__node_id == other.node_id and np.all(self._profile == other.profile) and \
134
134
  self.__source_type == other.source_type
135
135
 
136
136
  def __str__(self) -> str:
137
137
  return f"{super().__str__()} species_id: {self.__species_id} " +\
138
- f"node_id: {self.__node_id} profile: {self.__profile} source_type: {self.__source_type}"
138
+ f"node_id: {self.__node_id} profile: {self._profile} source_type: {self.__source_type}"
139
139
 
140
140
  def _get_pattern_id(self) -> str:
141
141
  return f"{self.__species_id}_{self.__node_id}"
@@ -160,7 +160,7 @@ class SpeciesInjectionEvent(SystemEvent, JsonSerializable):
160
160
  injection_time_start_idx = int(self.start_time / time_step)
161
161
 
162
162
  injection_pattern = None
163
- if len(self.__profile) == injection_pattern_length:
163
+ if len(self._profile) == injection_pattern_length:
164
164
  injection_pattern = self.profile
165
165
  else:
166
166
  injection_pattern = np.tile(self.profile,
@@ -93,7 +93,7 @@ class SensorFaultConstant(SensorFault, JsonSerializable):
93
93
  raise TypeError("'constant_shift' must be an instance of 'float' but no of " +
94
94
  f"'{type(constant_shift)}'")
95
95
 
96
- self.__constant_shift = constant_shift
96
+ self._constant_shift = constant_shift
97
97
 
98
98
  super().__init__(**kwds)
99
99
 
@@ -107,20 +107,20 @@ class SensorFaultConstant(SensorFault, JsonSerializable):
107
107
  `float`
108
108
  Constant that is added to the sensor reading.
109
109
  """
110
- return self.__constant_shift
110
+ return self._constant_shift
111
111
 
112
112
  def get_attributes(self) -> dict:
113
- return super().get_attributes() | {"constant_shift": self.__constant_shift}
113
+ return super().get_attributes() | {"constant_shift": self._constant_shift}
114
114
 
115
115
  def __eq__(self, other) -> bool:
116
- return super().__eq__(other) and self.__constant_shift == other.constant_shift
116
+ return super().__eq__(other) and self._constant_shift == other.constant_shift
117
117
 
118
118
  def __str__(self) -> str:
119
- return f"{type(self).__name__} {super().__str__()} constant: {self.__constant_shift}"
119
+ return f"{type(self).__name__} {super().__str__()} constant: {self._constant_shift}"
120
120
 
121
121
  def apply_sensor_fault(self, cur_multiplier: float, sensor_reading: float,
122
122
  cur_time: int) -> float:
123
- return sensor_reading + cur_multiplier * self.__constant_shift
123
+ return sensor_reading + cur_multiplier * self._constant_shift
124
124
 
125
125
 
126
126
  @serializable(SENSOR_FAULT_DRIFT_ID, ".epytflow_sensorfault_drift")
@@ -134,7 +134,7 @@ class SensorFaultDrift(SensorFault, JsonSerializable):
134
134
  Coefficient of the drift.
135
135
  """
136
136
  def __init__(self, coef: float, **kwds):
137
- self.__coef = coef
137
+ self._coef = coef
138
138
 
139
139
  super().__init__(**kwds)
140
140
 
@@ -148,20 +148,20 @@ class SensorFaultDrift(SensorFault, JsonSerializable):
148
148
  `float`
149
149
  Coefficient of the drift.
150
150
  """
151
- return self.__coef
151
+ return self._coef
152
152
 
153
153
  def get_attributes(self) -> dict:
154
- return super().get_attributes() | {"coef": self.__coef}
154
+ return super().get_attributes() | {"coef": self._coef}
155
155
 
156
156
  def __eq__(self, other) -> bool:
157
- return super().__eq__(other) and self.__coef == other.coef
157
+ return super().__eq__(other) and self._coef == other.coef
158
158
 
159
159
  def __str__(self) -> str:
160
- return f"{type(self).__name__} {super().__str__()} coef: {self.__coef}"
160
+ return f"{type(self).__name__} {super().__str__()} coef: {self._coef}"
161
161
 
162
162
  def apply_sensor_fault(self, cur_multiplier: float, sensor_reading: float,
163
163
  cur_time: int) -> float:
164
- return sensor_reading + cur_multiplier * (self.__coef * (cur_time - self.start_time))
164
+ return sensor_reading + cur_multiplier * (self._coef * (cur_time - self.start_time))
165
165
 
166
166
 
167
167
  @serializable(SENSOR_FAULT_GAUSSIAN_ID, ".epytflow_sensorfault_gaussian")
@@ -179,7 +179,7 @@ class SensorFaultGaussian(SensorFault, JsonSerializable):
179
179
  if not isinstance(std, float) or not std > 0:
180
180
  raise ValueError("'std' must be an instance of 'float' and be greater than 0")
181
181
 
182
- self.__std = std
182
+ self._std = std
183
183
 
184
184
  super().__init__(**kwds)
185
185
 
@@ -193,20 +193,20 @@ class SensorFaultGaussian(SensorFault, JsonSerializable):
193
193
  `float`
194
194
  Standard deviation of the Gaussian noise.
195
195
  """
196
- return self.__std
196
+ return self._std
197
197
 
198
198
  def get_attributes(self) -> dict:
199
- return super().get_attributes() | {"std": self.__std}
199
+ return super().get_attributes() | {"std": self._std}
200
200
 
201
201
  def __eq__(self, other) -> bool:
202
- return super().__eq__(other) and self.__std == other.std
202
+ return super().__eq__(other) and self._std == other.std
203
203
 
204
204
  def __str__(self) -> str:
205
- return f"{type(self).__name__} {super().__str__()} std: {self.__std}"
205
+ return f"{type(self).__name__} {super().__str__()} std: {self._std}"
206
206
 
207
207
  def apply_sensor_fault(self, cur_multiplier: float, sensor_reading: float,
208
208
  cur_time: int) -> float:
209
- return sensor_reading + cur_multiplier * np.random.normal(loc=0, scale=self.__std)
209
+ return sensor_reading + cur_multiplier * np.random.normal(loc=0, scale=self._std)
210
210
 
211
211
 
212
212
  @serializable(SENSOR_FAULT_PERCENTAGE_ID, ".epytflow_sensorfault_percentage",)
@@ -223,7 +223,7 @@ class SensorFaultPercentage(SensorFault, JsonSerializable):
223
223
  if not isinstance(coef, float) or not coef > 0:
224
224
  raise ValueError("'coef' must be an instance of 'float' and be greater than zero.")
225
225
 
226
- self.__coef = coef
226
+ self._coef = coef
227
227
 
228
228
  super().__init__(**kwds)
229
229
 
@@ -237,20 +237,20 @@ class SensorFaultPercentage(SensorFault, JsonSerializable):
237
237
  `float`
238
238
  Coefficient (percentage) of the shift.
239
239
  """
240
- return self.__coef
240
+ return self._coef
241
241
 
242
242
  def get_attributes(self) -> dict:
243
- return super().get_attributes() | {"coef": self.__coef}
243
+ return super().get_attributes() | {"coef": self._coef}
244
244
 
245
245
  def __eq__(self, other) -> bool:
246
- return super().__eq__(other) and self.__coef == other.coef
246
+ return super().__eq__(other) and self._coef == other.coef
247
247
 
248
248
  def __str__(self) -> str:
249
- return f"{type(self).__name__} {super().__str__()} coef: {self.__coef}"
249
+ return f"{type(self).__name__} {super().__str__()} coef: {self._coef}"
250
250
 
251
251
  def apply_sensor_fault(self, cur_multiplier: float, sensor_reading: float,
252
252
  cur_time: int) -> float:
253
- return sensor_reading + cur_multiplier * self.__coef * sensor_reading
253
+ return sensor_reading + cur_multiplier * self._coef * sensor_reading
254
254
 
255
255
 
256
256
  @serializable(SENSOR_FAULT_STUCKATZERO_ID, ".epytflow_sensorfault_zero")
@@ -13,7 +13,7 @@ class SystemEvent(Event):
13
13
  """
14
14
  def __init__(self, **kwds):
15
15
  self._epanet_api = None
16
- self.__exit_called = False
16
+ self._exit_called = False
17
17
 
18
18
  super().__init__(**kwds)
19
19
 
@@ -52,9 +52,9 @@ class SystemEvent(Event):
52
52
  if self.start_time <= cur_time < self.end_time:
53
53
  self.apply(cur_time)
54
54
  elif cur_time > self.end_time:
55
- if self.__exit_called is False:
55
+ if self._exit_called is False:
56
56
  self.exit(cur_time)
57
- self.__exit_called = True
57
+ self._exit_called = True
58
58
 
59
59
  def reset(self) -> None:
60
60
  """
@@ -167,9 +167,7 @@ class ScadaData(Serializable):
167
167
  raise TypeError("'sensor_readings_time' must be an instance of 'numpy.ndarray' " +
168
168
  f"but not of '{type(sensor_readings_time)}'")
169
169
  if warnings_code is None:
170
- warnings.warn("Loading a file that was created with an outdated version of EPyT-Flow" +
171
- " -- support of such old files will be removed in the next release!",
172
- DeprecationWarning)
170
+ warnings_code = [0] * len(sensor_readings_time)
173
171
  else:
174
172
  if not isinstance(warnings_code, np.ndarray):
175
173
  raise TypeError("'warnings_code' must be an instance of 'numpy.ndarray' " +
@@ -376,6 +374,8 @@ class ScadaData(Serializable):
376
374
  self.__sensor_readings = None
377
375
  self.__frozen_sensor_config = frozen_sensor_config
378
376
  self.__sensor_readings_time = sensor_readings_time
377
+ self.__sensor_readings_time_to_idx = {time: idx for idx, time in
378
+ enumerate(self.__sensor_readings_time)}
379
379
 
380
380
  if self.__frozen_sensor_config is False:
381
381
  self.__pressure_data_raw = pressure_data_raw
@@ -1713,7 +1713,7 @@ class ScadaData(Serializable):
1713
1713
  self.__sensor_reading_events = sensor_reading_events
1714
1714
  self.__init()
1715
1715
 
1716
- def extract_time_window(self, start_time: int, end_time: int):
1716
+ def extract_time_window(self, start_time: int, end_time: int = None):
1717
1717
  """
1718
1718
  Extracts a time window of SCADA data from this SCADA data instance --
1719
1719
  i.e. creating a new SCADA data instance containing data from the requested
@@ -1748,8 +1748,8 @@ class ScadaData(Serializable):
1748
1748
  else:
1749
1749
  end_time = self.__sensor_readings_time[-1]
1750
1750
 
1751
- start_idx = self.__sensor_readings_time.tolist().index(start_time)
1752
- end_idx = self.__sensor_readings_time.tolist().index(end_time) + 1
1751
+ start_idx = self.__sensor_readings_time_to_idx[start_time]
1752
+ end_idx = self.__sensor_readings_time_to_idx[end_time] + 1
1753
1753
 
1754
1754
  pressure_data_raw = None
1755
1755
  if self.__pressure_data_raw is not None:
@@ -2375,11 +2375,10 @@ class ScadaData(Serializable):
2375
2375
  mask = np.zeros(len(self.__sensor_config.nodes))
2376
2376
  node_features = np.array([[default_missing_value] * len(self.__sensor_config.nodes)
2377
2377
  for _ in range(len(self.__sensor_readings_time))])
2378
- nodes_id = self.__network_topo.get_all_nodes()
2379
2378
 
2380
2379
  pressure_readings = self.get_data_pressures()
2381
2380
  for pressures_idx, node_id in enumerate(self.__sensor_config.pressure_sensors):
2382
- idx = nodes_id.index(node_id)
2381
+ idx = self.__sensor_config.map_node_id_to_idx(node_id)
2383
2382
  node_features[:, idx] = pressure_readings[:, pressures_idx]
2384
2383
  mask[idx] = 1
2385
2384
 
@@ -2617,11 +2616,10 @@ class ScadaData(Serializable):
2617
2616
  mask = np.zeros(len(self.__sensor_config.nodes))
2618
2617
  node_features = np.array([[default_missing_value] * len(self.__sensor_config.nodes)
2619
2618
  for _ in range(len(self.__sensor_readings_time))])
2620
- nodes_id = self.__network_topo.get_all_nodes()
2621
2619
 
2622
2620
  demand_readings = self.get_data_demands()
2623
2621
  for demands_idx, node_id in enumerate(self.__sensor_config.demand_sensors):
2624
- idx = nodes_id.index(node_id)
2622
+ idx = self.__sensor_config.map_node_id_to_idx(node_id)
2625
2623
  node_features[:, idx] = demand_readings[:, demands_idx]
2626
2624
  mask[idx] = 1
2627
2625
 
@@ -2737,11 +2735,10 @@ class ScadaData(Serializable):
2737
2735
  mask = np.zeros(len(self.__sensor_config.nodes))
2738
2736
  node_features = np.array([[default_missing_value] * len(self.__sensor_config.nodes)
2739
2737
  for _ in range(len(self.__sensor_readings_time))])
2740
- nodes_id = self.__network_topo.get_all_nodes()
2741
2738
 
2742
2739
  node_quality_readings = self.get_data_nodes_quality()
2743
2740
  for quality_idx, node_id in enumerate(self.__sensor_config.quality_node_sensors):
2744
- idx = nodes_id.index(node_id)
2741
+ idx = self.__sensor_config.map_node_id_to_idx(node_id)
2745
2742
  node_features[:, idx] = node_quality_readings[:, quality_idx]
2746
2743
  mask[idx] = 1
2747
2744
 
@@ -3752,7 +3749,6 @@ class ScadaData(Serializable):
3752
3749
  masks = []
3753
3750
  results = []
3754
3751
 
3755
- all_nodes_id = self.__network_topo.get_all_nodes()
3756
3752
  bulk_species_sensor_locations = self.__sensor_config.bulk_species_node_sensors
3757
3753
 
3758
3754
  for species_id, nodes_id in bulk_species_sensor_locations.items():
@@ -3762,7 +3758,7 @@ class ScadaData(Serializable):
3762
3758
 
3763
3759
  sensor_readings = self.get_data_bulk_species_node_concentration({species_id: nodes_id})
3764
3760
  for sensor_readings_idx, node_id in enumerate(nodes_id):
3765
- idx = all_nodes_id.index(node_id)
3761
+ idx = self.__sensor_config.map_node_id_to_idx(node_id)
3766
3762
  node_features[:, idx] = sensor_readings[:, sensor_readings_idx]
3767
3763
  mask[idx] = 1
3768
3764