epyt-flow 0.9.0__py3-none-any.whl → 0.10.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.
@@ -3,6 +3,7 @@ Module provides a class for specifying scenario configurations.
3
3
  """
4
4
  from typing import Any
5
5
  from copy import deepcopy
6
+ import warnings
6
7
  import os
7
8
  import json
8
9
  from pathlib import Path
@@ -12,7 +13,7 @@ from ..uncertainty import AbsoluteGaussianUncertainty, RelativeGaussianUncertain
12
13
  AbsoluteUniformUncertainty, RelativeUniformUncertainty, ModelUncertainty, \
13
14
  SensorNoise, Uncertainty
14
15
  from .sensor_config import SensorConfig
15
- from .scada import AdvancedControlModule
16
+ from .scada import CustomControlModule, SimpleControlModule, ComplexControlModule
16
17
  from .events import SystemEvent, SensorReadingEvent
17
18
  from .events.sensor_faults import SensorFaultConstant, SensorFaultDrift, SensorFaultGaussian, \
18
19
  SensorFaultPercentage, SensorFaultStuckZero
@@ -63,8 +64,16 @@ class ScenarioConfig(Serializable):
63
64
  Speciation of sensor noise -- i.e. noise/uncertainty affecting the sensor readings.
64
65
 
65
66
  The default is None
66
- controls : list[:class:`~epyt_flow.simulation.scada.advanced_control.AdvancedControlModule`], optional
67
- List of control modules that are active during the simulation.
67
+ csutom_controls : list[:class:`~epyt_flow.simulation.scada.custom_control.CustomControlModule`], optional
68
+ List of custom control modules that are active during the simulation.
69
+
70
+ The default is an empty list.
71
+ simple_controls : list[:class:`~epyt_flow.simulation.scada.simple_control.SimpleControlModule`], optional
72
+ List of EPANET control rules that are active during the simulation.
73
+
74
+ The default is an empty list.
75
+ complex_controls : list[:class:`~epyt_flow.simulation.scada.complex_control.ComplexControlModule`], optional
76
+ List of complex (i.e. IF-THEN-ELSE) EPANET control rules that are active during the simulation.
68
77
 
69
78
  The default is an empty list.
70
79
  model_uncertainty : :class:`~epyt_flow.uncertainty.model_uncertainty.ModelUncertainty`, optional
@@ -82,11 +91,22 @@ class ScenarioConfig(Serializable):
82
91
  def __init__(self, scenario_config: Any = None, f_inp_in: str = None, f_msx_in: str = None,
83
92
  general_params: dict = None, sensor_config: SensorConfig = None,
84
93
  memory_consumption_estimate: float = None,
85
- controls: list[AdvancedControlModule] = [],
94
+ controls: list = None,
95
+ advanced_controls: list = None,
96
+ custom_controls: list[CustomControlModule] = [],
97
+ simple_controls: list[SimpleControlModule] = [],
98
+ complex_controls: list[ComplexControlModule] = [],
86
99
  sensor_noise: SensorNoise = None,
87
100
  model_uncertainty: ModelUncertainty = None,
88
101
  system_events: list[SystemEvent] = [],
89
102
  sensor_reading_events: list[SensorReadingEvent] = [], **kwds):
103
+ if controls is not None:
104
+ warnings.warn("'controls' is deprecated and will be removed in future releases")
105
+ advanced_controls = controls
106
+ if advanced_controls is not None:
107
+ warnings.warn("'advanced_controls' is deprecated and will be removed in " +
108
+ "future releases -- use 'custom_controls' instead")
109
+
90
110
  if f_inp_in is None and scenario_config is None:
91
111
  raise ValueError("Either 'f_inp_in' or 'scenario_config' must be given")
92
112
  if scenario_config is not None:
@@ -115,14 +135,32 @@ class ScenarioConfig(Serializable):
115
135
  if not isinstance(memory_consumption_estimate, float) or \
116
136
  memory_consumption_estimate <= 0:
117
137
  raise ValueError("'memory_consumption_estimate' must be a positive integer")
118
- if not isinstance(controls, list):
119
- raise TypeError("'controls' must be an instance of " +
120
- "'list[epyt_flow.simulation.scada.AdvancedControlModule]' but no of " +
121
- f"'{type(controls)}'")
122
- if len(controls) != 0:
123
- if any(not isinstance(c, AdvancedControlModule) for c in controls):
124
- raise TypeError("Each item in 'controls' must be an instance of " +
138
+ if advanced_controls is not None:
139
+ if not isinstance(advanced_controls, list):
140
+ raise TypeError("'advanced_controls' must be an instance of " +
141
+ "'list[epyt_flow.simulation.scada.AdvancedControlModule]' but no of " +
142
+ f"'{type(advanced_controls)}'")
143
+
144
+ from .scada.advanced_control import AdvancedControlModule
145
+ if any(not isinstance(c, AdvancedControlModule) for c in advanced_controls):
146
+ raise TypeError("Each item in 'advanced_controls' must be an instance of " +
125
147
  "'epyt_flow.simulation.scada.AdvancedControlModule'")
148
+ if len(custom_controls) != 0:
149
+ if any(not isinstance(c, CustomControlModule) for c in custom_controls):
150
+ raise TypeError("Each item in 'custom_controls' must be an instance of " +
151
+ "'epyt_flow.simulation.scada.CustomControlModule'")
152
+ if not isinstance(simple_controls, list):
153
+ raise TypeError("'simple_controls' must be an instance of " +
154
+ "'list[epyt_flow.simulation.scada.SimpleControlModule]' but no of " +
155
+ f"'{type(simple_controls)}'")
156
+ if len(simple_controls) != 0:
157
+ if any(not isinstance(c, SimpleControlModule) for c in simple_controls):
158
+ raise TypeError("Each item in 'simple_controls' must be an instance of " +
159
+ "'epyt_flow.simulation.scada.SimppleControlModule'")
160
+ if len(complex_controls) != 0:
161
+ if any(not isinstance(c, ComplexControlModule) for c in complex_controls):
162
+ raise TypeError("Each item in 'complex_controls' must be an instance of " +
163
+ "'epyt_flow.simulation.scada.ComplexControlModule'")
126
164
  if sensor_noise is not None:
127
165
  if not isinstance(sensor_noise, SensorNoise):
128
166
  raise TypeError("'sensor_noise' must be an instance of " +
@@ -169,10 +207,25 @@ class ScenarioConfig(Serializable):
169
207
  else:
170
208
  self.__memory_consumption_estimate = memory_consumption_estimate
171
209
 
172
- if len(controls) == 0:
173
- self.__controls = scenario_config.controls
210
+ self.__advanced_controls = advanced_controls
211
+ if advanced_controls is not None:
212
+ if len(advanced_controls) == 0:
213
+ self.__advanced_controls = scenario_config.advanced_controls
214
+
215
+ if len(custom_controls) == 0:
216
+ self.__custom_controls = scenario_config.custom_controls
217
+ else:
218
+ self.__custom_controls = custom_controls
219
+
220
+ if len(simple_controls) == 0:
221
+ self.__simple_controls = scenario_config.simple_controls
174
222
  else:
175
- self.__controls = controls
223
+ self.__simple_controls = simple_controls
224
+
225
+ if len(complex_controls) == 0:
226
+ self.__complex_controls = scenario_config.complex_controls
227
+ else:
228
+ self.__complex_controls = complex_controls
176
229
 
177
230
  if sensor_noise is None:
178
231
  self.__sensor_noise = scenario_config.sensor_noise
@@ -199,7 +252,10 @@ class ScenarioConfig(Serializable):
199
252
  self.__general_params = general_params
200
253
  self.__sensor_config = sensor_config
201
254
  self.__memory_consumption_estimate = memory_consumption_estimate
202
- self.__controls = controls
255
+ self.__advanced_controls = advanced_controls
256
+ self.__custom_controls = custom_controls
257
+ self.__simple_controls = simple_controls
258
+ self.__complex_controls = complex_controls
203
259
  self.__sensor_noise = sensor_noise
204
260
  self.__system_events = system_events
205
261
  self.__sensor_reading_events = sensor_reading_events
@@ -286,16 +342,53 @@ class ScenarioConfig(Serializable):
286
342
  return self.__memory_consumption_estimate
287
343
 
288
344
  @property
289
- def controls(self) -> list[AdvancedControlModule]:
345
+ def advanced_controls(self) -> list:
290
346
  """
291
- Gets the list of all control modules that are active during the simulation.
347
+ Gets the list of all (advanced) control modules that are active during the simulation.
292
348
 
293
349
  Returns
294
350
  -------
295
351
  list[:class:`~epyt_flow.simulation.scada.advanced_control.AdvancedControlModule`]
296
352
  List of all control modules that are active during the simulation.
297
353
  """
298
- return deepcopy(self.__controls)
354
+ return deepcopy(self.__advanced_controls)
355
+
356
+ @property
357
+ def custom_controls(self) -> list[CustomControlModule]:
358
+ """
359
+ Returns the list of all custom control modules that are active during the simulation.
360
+
361
+ Returns
362
+ -------
363
+ list[:class:`~epyt_flow.simulation.scada.custom_control.CustomControlModule`]
364
+ List of all custom control modules that are active during the simulation.
365
+ """
366
+ return deepcopy(self.__custom_controls)
367
+
368
+ @property
369
+ def simple_controls(self) -> list[SimpleControlModule]:
370
+ """
371
+ Gets the list of all EPANET control rules that are active during the simulation.
372
+
373
+ Returns
374
+ -------
375
+ list[:class:`~epyt_flow.simulation.scada.simple_control.SimpleControlModule`]
376
+ List of all EPANET control rules that are active during the simulation.
377
+ """
378
+ return deepcopy(self.__simple_controls)
379
+
380
+ @property
381
+ def complex_controls(self) -> list[ComplexControlModule]:
382
+ """
383
+ Gets the list of all complex (i.e. IF-THEN-ELSE) EPANET control rules
384
+ that are active during the simulation.
385
+
386
+ Returns
387
+ -------
388
+ list[:class:`~epyt_flow.simulation.scada.complex_control.ComplexControlModule`]
389
+ List of all complex EPANET control rules that are active during the simulation.
390
+ """
391
+ return deepcopy(self.__complex_controls)
299
392
 
300
393
  @property
301
394
  def sensor_noise(self) -> SensorNoise:
@@ -350,7 +443,9 @@ class ScenarioConfig(Serializable):
350
443
  "general_params": self.__general_params,
351
444
  "sensor_config": self.__sensor_config,
352
445
  "memory_consumption_estimate": self.__memory_consumption_estimate,
353
- "controls": self.__controls,
446
+ "custom_controls": self.__custom_controls,
447
+ "simple_controls": self.__simple_controls,
448
+ "complex_controls": self.__complex_controls,
354
449
  "sensor_noise": self.__sensor_noise,
355
450
  "model_uncertainty": self.__model_uncertainty,
356
451
  "system_events": self.__system_events,
@@ -367,7 +462,10 @@ class ScenarioConfig(Serializable):
367
462
  and self.__general_params == other.general_params \
368
463
  and self.__memory_consumption_estimate == other.memory_consumption_estimate \
369
464
  and self.__sensor_config == other.sensor_config \
370
- and np.all(self.__controls == other.controls) \
465
+ and np.all(self.__advanced_controls == other.advanced_controls) \
466
+ and np.all(self.__custom_controls == other.custom_controls) \
467
+ and np.all(self.__simple_controls == other.simple_controls) \
468
+ and np.all(self.__complex_controls == other.complex_controls) \
371
469
  and self.__model_uncertainty == other.model_uncertainty \
372
470
  and np.all(self.__system_events == other.system_events) \
373
471
  and np.all(self.__sensor_reading_events == other.sensor_reading_events)
@@ -376,8 +474,10 @@ class ScenarioConfig(Serializable):
376
474
  return f"f_inp_in: {self.f_inp_in} f_msx_in: {self.f_msx_in} " + \
377
475
  f"general_params: {self.general_params} sensor_config: {self.sensor_config} " + \
378
476
  f"memory_consumption_estimate: {self.memory_consumption_estimate} " + \
379
- f"controls: {self.controls} sensor_noise: {self.sensor_noise} " + \
380
- f"model_uncertainty: {self.model_uncertainty} " + \
477
+ f"advanced_controls: {self.advanced_controls} simple_controls: {self.simple_controls} " + \
478
+ f"complex_controls: {self.__complex_controls} " + \
479
+ f"custom_controls: {self.__custom_controls}" + \
480
+ f"sensor_noise: {self.sensor_noise} model_uncertainty: {self.model_uncertainty} " + \
381
481
  f"system_events: {','.join(map(str, self.system_events))} " + \
382
482
  f"sensor_reading_events: {','.join(map(str, self.sensor_reading_events))}"
383
483
 
@@ -614,6 +714,6 @@ class ScenarioConfig(Serializable):
614
714
 
615
715
  # Create final scenario configuration
616
716
  return ScenarioConfig(f_inp_in=f_inp_in, f_msx_in=f_msx_in, general_params=general_params,
617
- sensor_config=sensor_config, controls=[], sensor_noise=sensor_noise,
717
+ sensor_config=sensor_config, sensor_noise=sensor_noise,
618
718
  model_uncertainty=model_uncertainty, system_events=leakages,
619
719
  sensor_reading_events=sensor_faults)