Visualization Example

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

This example demonstrates the usage of the visualization class in order to plot network topology and simulation data per hydraulic component.

[2]:
%pip install epyt-flow --quiet
Note: you may need to restart the kernel to use updated packages.
[3]:
from epyt_flow.data.networks import load_anytown
from epyt_flow.simulation import ScenarioSimulator
from epyt_flow.visualization import ScenarioVisualizer

Load Anytown network by calling load_anytown():

[4]:
network_config = load_anytown(verbose=False)

Create a dummy ScenarioSimulator:

[5]:
wdn = ScenarioSimulator(scenario_config=network_config)

Plot the network by creating a new ScenarioVisualizer object and calling show_plot() :

[6]:
vis = ScenarioVisualizer(wdn)
vis.show_plot()
../_images/examples_visualization_10_0.png

The hydraulic components can be colored according to the simulation results by calling the corresponding functions: color_nodes(), color_links() , color_pumps() , color_tanks() and color_valves() . The parameters (e.g. pressure, diameter) are component specific and can be found in the function documentation. The statistic options are the same for the different components and include mean, min, max and time_step. When using the values at a certain timestep, a point in time must be given through the pit parameter.

This example shows the nodes in this function colored according to the pressure at timestep 8.

[7]:
vis = ScenarioVisualizer(wdn)
vis.color_nodes(parameter='pressure', statistic='time_step', pit=8,
                colormap='autumn', show_colorbar=True)
vis.show_plot()
../_images/examples_visualization_12_0.png

Additionally to the color_links() method, it is possible to resize the links according to a parameter. Multiple manipulations can be applied to the same graph at once. If several calls are made to color the same hydraulic component, only the last call is valid.

[8]:
vis = ScenarioVisualizer(wdn)
vis.color_links(parameter='flow_rate', statistic='mean', show_colorbar=True)
vis.resize_links(parameter='flow_rate', statistic='mean')
vis.hide_nodes()
vis.show_plot()
../_images/examples_visualization_14_0.png

In order to apply a certain color scheme do all hydraulic components that are not affected by method calls, import the color scheme and apply it when creating the ScenarioVisualizer.

[9]:
from epyt_flow.visualization import epanet_colors, black_colors

vis = ScenarioVisualizer(wdn, color_scheme=epanet_colors)
vis.show_plot()
../_images/examples_visualization_16_0.png

The colors applied to a component don’t have to be continuous. It is possible to either supply an amount of intervals the components should be grouped into by using intervals=3 or to custom divide them by supplying the borders through intervals=[-100, 0, 100].

Conversions to different units can also be applied by using a dictionary containing the required epyt-flow conversion units.

[10]:
vis = ScenarioVisualizer(wdn, color_scheme=black_colors)
vis.color_nodes(parameter='demand', statistic='time_step', pit=0,
                colormap='autumn', intervals=3, conversion={"flow_unit": 8})
vis.show_plot()
../_images/examples_visualization_18_0.png
[11]:
vis = ScenarioVisualizer(wdn, color_scheme=black_colors)
vis.color_links(parameter='flow_rate', statistic='max', colormap='autumn',
                intervals=[-100, 0, 100, 200])
vis.hide_nodes()
vis.show_plot()
../_images/examples_visualization_19_0.png

The colormap can be adjusted by providing a matplotlib colormap as a parameter.

[12]:
vis = ScenarioVisualizer(wdn, color_scheme=black_colors)
vis.color_links(parameter='diameter', colormap='Blues')
vis.resize_links(parameter='diameter', line_widths=(1, 3))
vis.hide_nodes()
vis.show_plot()
../_images/examples_visualization_21_0.png

Components can be labeld by calling add_labels(). The labels can be added for the sensor_config (see below), for all components via 'all' or for certain components by using a list of the components names which should be labeled: ['nodes', 'tanks', 'reservoirs', 'pipes', 'valves', 'pumps'].

[13]:
from epyt_flow.data.networks import load_hanoi
from epyt_flow.visualization import epyt_flow_colors

network_config_sc = load_hanoi(verbose=False,
                               include_default_sensor_placement=True)
wdn_sc = ScenarioSimulator(scenario_config=network_config_sc)
vis = ScenarioVisualizer(wdn_sc, color_scheme=epyt_flow_colors)
vis.highlight_sensor_config()
vis.add_labels('sensor_config', font_size=10)
vis.show_plot()
wdn_sc.close()
../_images/examples_visualization_23_0.png

Given a set of sensor applied to a water distribution network, it is possible to use the sensor data (instead of the raw simulation data) for visualization. Sensors may differ in values to the raw data due to sensor faults or noise. To do this, set the use_sensor_data flag to True, when coloring a component:

[14]:
network_config = load_hanoi(verbose=False, include_default_sensor_placement=False)
wdn_sc = ScenarioSimulator(scenario_config=network_config)
wdn_sc.set_pressure_sensors(['5', '25', '17', '20', '11'])
vis = ScenarioVisualizer(wdn_sc, color_scheme=black_colors)
vis.color_nodes(parameter="pressure", use_sensor_data=True)
vis.add_labels('sensor_config', font_size=10)
vis.show_plot()
wdn_sc.close()
../_images/examples_visualization_25_0.png

Note that in this case, the pressure can only be shown for nodes that have a pressure sensor attached to them.

Animations

It is possible to do an animation of the timestep values over an interval in time. For this, the point in time (pit) parameter must be provided as a tuple of the start and end values. Further, instead of calling show_plot() , show_animation() must be selected. If a file_path (anim.gif) is provided through the export_to_file parameter, the resulting animation is saved.

[15]:
from IPython.display import HTML

vis = ScenarioVisualizer(wdn, color_scheme=black_colors)
vis.color_links(parameter='flow_rate', statistic='time_step', pit=(0, 40))
vis.resize_links(parameter='flow_rate', statistic='time_step', pit=(0, 40),
                 line_widths=(1, 3))
vis.hide_nodes()
anim = vis.show_animation(return_animation=True)
HTML(anim.to_jshtml())
[15]:
<Figure size 640x480 with 0 Axes>

It is also possible to use custom data, instead of generated scada data, to visualize behaviour. In this example, periodic flow rates are animated over time. The necessary dimensions for the custom data are: time_steps x links. For other hydraulic components, it would be: time_steps x hydraulic_components.

[16]:
import numpy as np

# Generate custom data for better demonstration
timesteps = 50
links = 41
t = np.linspace(0, 2 * np.pi, timesteps)

frequencies = np.linspace(1, 3, links)
phases = np.linspace(0, np.pi, links)
amplitudes = np.linspace(0.5, 1.5, links)

custom_data_table = np.array([a * np.sin(f * t + p) for f, p, a in
                              zip(frequencies, phases, amplitudes)]).T

# Create new ScenarioVisualizer with black color scheme
vis = ScenarioVisualizer(wdn, color_scheme=black_colors)

# Visualize the custom data from time step 0 to the last time step (-1) as
# link color and link size
vis.color_links(data=custom_data_table, parameter='custom_data',
                statistic='time_step', pit=(0, -1))
vis.resize_links(data=custom_data_table, parameter='custom_data',
                 statistic='time_step', pit=(0, -1), line_widths=(1, 3))

# Hide the nodes such that only the links remain visible
vis.hide_nodes()

anim = vis.show_animation(return_animation=True)
HTML(anim.to_jshtml(fps=15))
[16]:
<Figure size 640x480 with 0 Axes>

Please close the simulator after use:

[17]:
wdn.close()