{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Event Detection Example" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import display, HTML\n", "display(HTML('\"Open'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example demonstrates how to create a scenario containing some events that have to be detected." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pip install epyt-control --quiet" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from epyt_flow.data.networks import load_ltown\n", "from epyt_flow.simulation import ScenarioSimulator\n", "from epyt_flow.simulation.events import AbruptLeakage, IncipientLeakage, SensorFaultDrift\n", "from epyt_flow.simulation import SENSOR_TYPE_LINK_FLOW\n", "from epyt_flow.utils import to_seconds, time_points_to_one_hot_encoding\n", "from epyt_control.signal_processing import SensorInterpolationDetector" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create new scenario based on the [L-Town network](https://epyt-flow.readthedocs.io/en/stable/epyt_flow.data.html#epyt_flow.data.networks.load_ltown) with a default sensor configuration and realistic demand patterns:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "config = load_ltown(use_realistic_demands=True,\n", " include_default_sensor_placement=True,\n", " verbose=False)\n", "\n", "scenario = ScenarioSimulator(scenario_config=config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set simulation duration to 2 weeks and use 5min time intervals:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "params = {\"simulation_duration\": to_seconds(days=14),\n", " \"hydraulic_time_step\": to_seconds(minutes=5),\n", " \"reporting_time_step\": to_seconds(minutes=5)}\n", "scenario.set_general_parameters(**params)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Add an abrupt leakage and a slightly larger incipient leakage in the second week:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "leak1 = AbruptLeakage(link_id=\"p673\", diameter=0.001,\n", " start_time=to_seconds(days=7),\n", " end_time=to_seconds(days=8))\n", "scenario.add_leakage(leak1)\n", "\n", "leak2 = IncipientLeakage(link_id=\"p31\", diameter=0.02,\n", " start_time=to_seconds(days=11),\n", " end_time=to_seconds(days=13),\n", " peak_time=to_seconds(days=12))\n", "scenario.add_leakage(leak2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Add sensor fault to one of the flow sensors:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sensor_fault = SensorFaultDrift(coef=1.1, sensor_id=\"p227\",\n", " sensor_type=SENSOR_TYPE_LINK_FLOW,\n", " start_time=to_seconds(days=9),\n", " end_time=to_seconds(days=10))\n", "scenario.add_sensor_fault(sensor_fault)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Run the entire simulation:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scada_data = scenario.run_simulation(verbose=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Prepare simulation results for calibrating an event detection method -- e.g. the [time_points_to_one_hot_encoding()](https://epyt-flow.readthedocs.io/en/stable/epyt_flow.html#epyt_flow.utils.time_points_to_one_hot_encoding) function can be used to create the labels:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X = np.concatenate((scada_data.get_data_pressures(), scada_data.get_data_flows()), axis=1)\n", "\n", "events_times = [int(t / params[\"hydraulic_time_step\"])\n", " for t in scenario.get_events_active_time_points()]\n", "y = time_points_to_one_hot_encoding(events_times, total_length=X.shape[0])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "split_point = 2000\n", "X_train, y_train = X[:split_point, :], y[:split_point]\n", "X_test, y_test = X[split_point:, :], y[split_point:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create and calibrate (i.e. fit) a [simple event detector](https://epyt-control.readthedocs.io/en/stable/epyt_control.signal_processing.event_detection.html#epyt_control.signal_processing.event_detection.sensor_interpolation_detector.SensorInterpolationDetector) to the first week of simulated data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "detector = SensorInterpolationDetector()\n", "detector.fit(X_train)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Apply the event detector to second week:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "suspicious_time_points = detector.apply(X_test)\n", "y_test_pred = time_points_to_one_hot_encoding(suspicious_time_points, X_test.shape[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Show the results:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.figure()\n", "plt.plot(list(range(len(y_test))), y_test, color=\"red\", label=\"Ground truth event\")\n", "plt.bar(list(range(len(y_test_pred))), y_test_pred, label=\"Raised alarm\")\n", "plt.legend()\n", "plt.ylabel(\"Event indicator\")\n", "plt.yticks([0, 1], [\"Inactive\", \"Active\"])\n", "plt.xlabel(\"Time (5min steps)\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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.\n", "\n", "More sophisticated event detection methods are likely to show a better performance." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Do not forget to close the simulation!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scenario.close()" ] } ], "metadata": { "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.16" } }, "nbformat": 4, "nbformat_minor": 2 }