Event Detection Example

[1]:
from IPython.display import display, HTML
display(HTML('<a target="_blank" href="https://colab.research.google.com/github/WaterFutures/EPyT-Control/blob/main/docs/examples/event_detection.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a>'))
Open In Colab

This example demonstrates how to create a scenario containing some events that have to be detected.

[2]:
%pip install epyt-control --quiet
Note: you may need to restart the kernel to use updated packages.
[3]:
import numpy as np
import matplotlib.pyplot as plt
from epyt_flow.data.networks import load_ltown
from epyt_flow.simulation import ScenarioSimulator
from epyt_flow.simulation.events import AbruptLeakage, IncipientLeakage, SensorFaultDrift
from epyt_flow.simulation import SENSOR_TYPE_LINK_FLOW
from epyt_flow.utils import to_seconds, time_points_to_one_hot_encoding
from epyt_control.signal_processing import SensorInterpolationDetector

Create new scenario based on the L-Town network with a default sensor configuration and realistic demand patterns:

[4]:
config = load_ltown(use_realistic_demands=True,
                    include_default_sensor_placement=True,
                    verbose=False)

scenario = ScenarioSimulator(scenario_config=config)

Set simulation duration to 2 weeks and use 5min time intervals:

[5]:
params = {"simulation_duration": to_seconds(days=14),
          "hydraulic_time_step": to_seconds(minutes=5),
          "reporting_time_step": to_seconds(minutes=5)}
scenario.set_general_parameters(**params)

Add an abrupt leakage and a slightly larger incipient leakage in the second week:

[6]:
leak1 = AbruptLeakage(link_id="p673", diameter=0.001,
                      start_time=to_seconds(days=7),
                      end_time=to_seconds(days=8))
scenario.add_leakage(leak1)

leak2 = IncipientLeakage(link_id="p31", diameter=0.02,
                         start_time=to_seconds(days=11),
                         end_time=to_seconds(days=13),
                         peak_time=to_seconds(days=12))
scenario.add_leakage(leak2)

Add sensor fault to one of the flow sensors:

[7]:
sensor_fault = SensorFaultDrift(coef=1.1, sensor_id="p227",
                                sensor_type=SENSOR_TYPE_LINK_FLOW,
                                start_time=to_seconds(days=9),
                                end_time=to_seconds(days=10))
scenario.add_sensor_fault(sensor_fault)

Run the entire simulation:

[8]:
scada_data = scenario.run_simulation(verbose=False)

Prepare simulation results for calibrating an event detection method – e.g. the time_points_to_one_hot_encoding() function can be used to create the labels:

[9]:
X = np.concatenate((scada_data.get_data_pressures(), scada_data.get_data_flows()), axis=1)

events_times = [int(t / params["hydraulic_time_step"])
                for t in scenario.get_events_active_time_points()]
y = time_points_to_one_hot_encoding(events_times, total_length=X.shape[0])
[10]:
split_point = 2000
X_train, y_train = X[:split_point, :], y[:split_point]
X_test, y_test = X[split_point:, :], y[split_point:]

Create and calibrate (i.e. fit) a simple event detector to the first week of simulated data:

[11]:
detector = SensorInterpolationDetector()
detector.fit(X_train)

Apply the event detector to second week:

[12]:
suspicious_time_points = detector.apply(X_test)
y_test_pred = time_points_to_one_hot_encoding(suspicious_time_points, X_test.shape[0])

Show the results:

[13]:
plt.figure()
plt.plot(list(range(len(y_test))), y_test, color="red", label="Ground truth event")
plt.bar(list(range(len(y_test_pred))), y_test_pred, label="Raised alarm")
plt.legend()
plt.ylabel("Event indicator")
plt.yticks([0, 1], ["Inactive", "Active"])
plt.xlabel("Time (5min steps)")
plt.show()
../_images/examples_event_detection_23_0.png

The event detector is able to detect the second event (sensor fault at a flow sensor), but it has difficulties detecting the first event and completely fails to detect the last event (incipient leakage). Note that the sensor fault (in this example) is much easier to detect than the leakages.

More sophisticated event detection methods are likely to show a better performance.

Do not forget to close the simulation!

[14]:
scenario.close()