From eb5765ed4b676480c9adeddb77b9f61697604797 Mon Sep 17 00:00:00 2001 From: Jolando Kisse Date: Mon, 21 Nov 2022 19:04:57 +0100 Subject: [PATCH 1/4] add simple_plotly function for pandapipes * only tested with gas grids * some components are still missing (heat exchanger, compressor...) --- pandapipes/plotting/plotly/__init__.py | 0 pandapipes/plotting/plotly/simple_plotly.py | 141 ++++++++++++++++++++ pandapipes/plotting/plotly/traces.py | 39 ++++++ 3 files changed, 180 insertions(+) create mode 100644 pandapipes/plotting/plotly/__init__.py create mode 100644 pandapipes/plotting/plotly/simple_plotly.py create mode 100644 pandapipes/plotting/plotly/traces.py diff --git a/pandapipes/plotting/plotly/__init__.py b/pandapipes/plotting/plotly/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pandapipes/plotting/plotly/simple_plotly.py b/pandapipes/plotting/plotly/simple_plotly.py new file mode 100644 index 00000000..01ce10e2 --- /dev/null +++ b/pandapipes/plotting/plotly/simple_plotly.py @@ -0,0 +1,141 @@ +# Copyright (c) 2022 by Fraunhofer Institute for Energy Economics +# and Energy System Technology (IEE), Kassel, and University of Kassel. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +import pandas as pd + +from pandapipes.plotting.plotly.traces import create_junction_trace, create_pipe_trace +from pandapower.plotting.plotly.simple_plotly import _simple_plotly_generic, draw_traces + +try: + from pandaplan.core import pplog as logging +except ImportError: + import logging +logger = logging.getLogger(__name__) + + +def get_hoverinfo(net, element, precision=3, sub_index=None): + hover_index = net[element].index + if element == "junction": + sink_str, source_str = [], [] + if hasattr(net, "sink"): + for ln in [net.sink.loc[net.sink.junction == b, "mdot_kg_per_s"].sum() for b in + net.junction.index]: + sink_str.append("Sink: {:.3f} kg/s
".format(ln) if ln != 0. else "") + if hasattr(net, "source"): + for s in [net.source.loc[net.source.junction == b, "mdot_kg_per_s"].sum() for b in + net.junction.index]: + source_str.append("Source: {:.3f} kg/s
".format(s) if s != 0. else "") + hoverinfo = ( + "Index: " + net.junction.index.astype(str) + "
" + + "Name: " + net.junction['name'].astype(str) + "
" + + "Height: " + net.junction['height_m'].astype(str) + " m
" + + "Pressure: " + net.junction['pn_bar'].round(precision).astype(str) + " bar
" + + "Temp.: " + net.junction['tfluid_k'].round(precision).astype(str) + " K
" + # + sink_str + source_str # TODO: fix this (correct indexing) + ).tolist() + elif element == "pipe": + hoverinfo = ( + "Index: " + net.pipe.index.astype(str) + "
" + + "Name: " + net.pipe['name'].astype(str) + "
" + + "Length: " + net.pipe['length_km'].round(precision).astype(str) + " km
" + + "Diameter: " + ((net.pipe['diameter_m']).round(precision)*1e3).astype(str) + " mm" + + "
" + + "k: " + (net.pipe['k_mm']).round(precision).astype(str) + " mm
" + ).tolist() + elif element == "pump": + hoverinfo = ( + "Index: " + net.pump.index.astype(str) + "
" + + "Name: " + net.pump['name'].astype(str) + "
" + + "Std. Type: " + net.pump['std_type'] + "
" + ).tolist() + elif element == "compressor": + hoverinfo = ( + "Index: " + net.compressor.index.astype(str) + "
" + + "Name: " + net.compressor['name'].astype(str) + "
" + + "Pressure ratio: " + net.compressor['pressure_ratio'] + "
" + ).tolist() + elif element == "pressure_control": + hoverinfo = ( + "Index: " + net.pressure_control.index.astype(str) + "
" + + "Name: " + net.pressure_control['name'].astype(str) + "
" + + "controlled junction:" + net.pressure_control['controlled_junction'] + "
" + + "controlled pressure:" + net.pressure_control['controlled_p_bar'] + " bar
" + ).tolist() + elif element == "ext_grid": + hoverinfo = ( + "Index: " + net.ext_grid.index.astype(str) + "
" + + "Name: " + net.ext_grid['name'].astype(str) + "
" + + "Pressure: " + net.ext_grid['p_bar'].round(precision).astype(str) + " bar
" + + "Temp.: " + net.ext_grid['t_k'].round(precision).astype(str) + " K
" + ).tolist() + + hover_index = net.ext_grid.junction.tolist() + elif element == "valve": + hoverinfo = ( + "Index: " + net.valve.index.astype(str) + "
" + + "Name: " + net.valve['name'].astype(str) + "
" + + "Open: " + net.valve['opened'].astype(str) + "
" + + "Diameter: " + ((net.valve['diameter_m']).round(precision)*1e3).astype(str) + + " mm
" + ).tolist() + else: + return None + hoverinfo = pd.Series(index=hover_index, data=hoverinfo) + if sub_index is not None: + hoverinfo = hoverinfo.loc[list(sub_index)] + return hoverinfo + + +def simple_plotly(net, use_pipe_geodata=None, on_map=False, + projection=None, map_style='basic', figsize=1, aspectratio='auto', pipe_width=1, + junction_size=10, ext_grid_size=20.0, junction_color="blue", pipe_color='grey', + pressure_reg_color='green', ext_grid_color="yellow", filename='temp-plot.html', + auto_open=True, showlegend=True, additional_traces=None): + respect_valves = False # TODO, not implemented yet + node_element = "junction" + branch_element = "pipe" + trans_element = "pump" + separator_element = "valve" + + traces, settings = _simple_plotly_generic(net=net, + respect_separators=respect_valves, + use_branch_geodata=use_pipe_geodata, + on_map=on_map, + projection=projection, + map_style=map_style, + figsize=figsize, + aspectratio=aspectratio, + branch_width=pipe_width, + node_size=junction_size, + ext_grid_size=ext_grid_size, + node_color=junction_color, + branch_color=pipe_color, + trafo_color=pressure_reg_color, + trafo3w_color=pressure_reg_color, + ext_grid_color=ext_grid_color, + node_element=node_element, + branch_element=branch_element, + trans_element=trans_element, + trans3w_element=None, + separator_element=separator_element, + branch_trace_func=create_pipe_trace, + node_trace_func=create_junction_trace, + hoverinfo_func=get_hoverinfo, + filename=filename, + auto_open=auto_open, + showlegend=showlegend) + + if additional_traces: + if isinstance(additional_traces, dict): + traces.append(additional_traces) + else: + traces.extend(additional_traces) + + return draw_traces(traces, **settings) + + +if __name__ == '__main__': + from pandapipes.networks import gas_versatility + net = gas_versatility() + simple_plotly(net) diff --git a/pandapipes/plotting/plotly/traces.py b/pandapipes/plotting/plotly/traces.py new file mode 100644 index 00000000..4e4cd382 --- /dev/null +++ b/pandapipes/plotting/plotly/traces.py @@ -0,0 +1,39 @@ +# Copyright (c) 2022 by Fraunhofer Institute for Energy Economics +# and Energy System Technology (IEE), Kassel, and University of Kassel. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +from pandapower.plotting.plotly.traces import _create_node_trace, _create_branch_trace, \ + draw_traces + + +def create_junction_trace(net, junctions=None, size=5, patch_type="circle", color="blue", + infofunc=None, trace_name='junctions', legendgroup=None, cmap=None, + cmap_vals=None, cbar_title=None, cmin=None, cmax=None, cpos=1.0, + colormap_column="p_bar"): + + node_element = "junction" + branch_element = "pipe" + + return _create_node_trace(net=net, nodes=junctions, size=size , patch_type=patch_type, + color=color, infofunc=infofunc, trace_name=trace_name, + legendgroup=legendgroup, cmap=cmap, cmap_vals=cmap_vals, + cbar_title=cbar_title, cmin=cmin, cmax=cmax, cpos=cpos, + colormap_column=colormap_column, + node_element=node_element, branch_element=branch_element) + + +def create_pipe_trace(net, pipes=None, use_pipe_geodata=True, respect_valves=False, width=1.0, + color='grey', infofunc=None, trace_name='pipes', legendgroup='pipes', + cmap=None, cbar_title=None, show_colorbar=True, cmap_vals=None, cmin=None, + cmax=None, cpos=1.1): + branch_element = "pipe" + node_element = "junction" + separator_element = "valve" + + return _create_branch_trace(net=net, branches=pipes, use_branch_geodata=use_pipe_geodata, + respect_separators=respect_valves, width=width, color=color, + infofunc=infofunc, trace_name=trace_name, legendgroup=legendgroup, + cmap=cmap, cbar_title=cbar_title, show_colorbar=show_colorbar, + cmap_vals=cmap_vals, cmin=cmin, cmax=cmax, cpos=cpos, + branch_element=branch_element, separator_element=separator_element, + node_element=node_element, cmap_vals_category="vmean_m_s") From d027ffdc75edad72052d89e51d38fbed17ca2bed Mon Sep 17 00:00:00 2001 From: Jolando Kisse Date: Mon, 27 Nov 2023 15:23:16 +0100 Subject: [PATCH 2/4] add simple functions for valve and compressor traces in plotly --- pandapipes/plotting/plotly/simple_plotly.py | 18 ++++++-- pandapipes/plotting/plotly/traces.py | 49 +++++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/pandapipes/plotting/plotly/simple_plotly.py b/pandapipes/plotting/plotly/simple_plotly.py index 01ce10e2..0faee2c8 100644 --- a/pandapipes/plotting/plotly/simple_plotly.py +++ b/pandapipes/plotting/plotly/simple_plotly.py @@ -4,7 +4,8 @@ import pandas as pd -from pandapipes.plotting.plotly.traces import create_junction_trace, create_pipe_trace +from pandapipes.plotting.plotly.traces import create_junction_trace, create_pipe_trace, \ + create_valve_trace, create_compressor_trace from pandapower.plotting.plotly.simple_plotly import _simple_plotly_generic, draw_traces try: @@ -89,8 +90,10 @@ def get_hoverinfo(net, element, precision=3, sub_index=None): def simple_plotly(net, use_pipe_geodata=None, on_map=False, projection=None, map_style='basic', figsize=1, aspectratio='auto', pipe_width=1, - junction_size=10, ext_grid_size=20.0, junction_color="blue", pipe_color='grey', - pressure_reg_color='green', ext_grid_color="yellow", filename='temp-plot.html', + junction_size=10, ext_grid_size=20.0, valve_size=3.0, compressor_size=3, + junction_color="blue", pipe_color='grey', pressure_reg_color='green', + ext_grid_color="yellow", valve_color="black", compressor_color="cyan", + filename='temp-plot.html', auto_open=True, showlegend=True, additional_traces=None): respect_valves = False # TODO, not implemented yet node_element = "junction" @@ -125,7 +128,16 @@ def simple_plotly(net, use_pipe_geodata=None, on_map=False, filename=filename, auto_open=auto_open, showlegend=showlegend) + if "valve" in net.keys() and len(net.valve) > 0: + traces.extend(create_valve_trace(net, valves=net.valve.loc[net.valve.opened].index, + size=valve_size, color=valve_color, + trace_name="open valves")) + traces.extend(create_valve_trace(net, valves=net.valve.loc[~net.valve.opened].index, + size=valve_size, color=valve_color, dash="dot", + trace_name="closed valves")) + if "compressor" in net.keys() and len(net.compressor) > 0: + traces.extend(create_compressor_trace(net, size=compressor_size, color=compressor_color)) if additional_traces: if isinstance(additional_traces, dict): traces.append(additional_traces) diff --git a/pandapipes/plotting/plotly/traces.py b/pandapipes/plotting/plotly/traces.py index 4e4cd382..aa5e029c 100644 --- a/pandapipes/plotting/plotly/traces.py +++ b/pandapipes/plotting/plotly/traces.py @@ -37,3 +37,52 @@ def create_pipe_trace(net, pipes=None, use_pipe_geodata=True, respect_valves=Fal cmap_vals=cmap_vals, cmin=cmin, cmax=cmax, cpos=cpos, branch_element=branch_element, separator_element=separator_element, node_element=node_element, cmap_vals_category="vmean_m_s") + + +def create_valve_trace(net, valves=None, use_valve_geodata=False, size=1.0, + color='black', infofunc=None, trace_name='valves', legendgroup='valves', + dash="solid"): + branch_element = "valve" + node_element = "junction" + separator_element = "valve" + respect_valves = False + cmap = None + cbar_title = None + show_colorbar = True + cmap_vals = None + cmin = None + cmax = None + cpos = 1.1 + + return _create_branch_trace(net=net, branches=valves, use_branch_geodata=use_valve_geodata, + respect_separators=respect_valves, width=size, color=color, + infofunc=infofunc, trace_name=trace_name, legendgroup=legendgroup, + cmap=cmap, cbar_title=cbar_title, show_colorbar=show_colorbar, + cmap_vals=cmap_vals, cmin=cmin, cmax=cmax, cpos=cpos, + branch_element=branch_element, separator_element=separator_element, + node_element=node_element, cmap_vals_category="vmean_m_s", + dash=dash) + + +def create_compressor_trace(net, compressors=None, use_pipe_geodata=False, size=3.0, + color='cyan', infofunc=None, trace_name='compressors', + legendgroup='compressors'): + branch_element = "compressor" + node_element = "junction" + separator_element = "valve" + respect_valves = False + cmap = None + cbar_title = None + show_colorbar = True + cmap_vals = None + cmin = None + cmax = None + cpos = 1.1 + + return _create_branch_trace(net=net, branches=compressors, use_branch_geodata=use_pipe_geodata, + respect_separators=respect_valves, width=size, color=color, + infofunc=infofunc, trace_name=trace_name, legendgroup=legendgroup, + cmap=cmap, cbar_title=cbar_title, show_colorbar=show_colorbar, + cmap_vals=cmap_vals, cmin=cmin, cmax=cmax, cpos=cpos, + branch_element=branch_element, separator_element=separator_element, + node_element=node_element, cmap_vals_category="compr_power_mw") \ No newline at end of file From 3f10317e1e8332e78748239e2e4bc2390cfe0993 Mon Sep 17 00:00:00 2001 From: Jolando Kisse Date: Fri, 20 Dec 2024 14:24:31 +0100 Subject: [PATCH 3/4] add pressure control trace --- pandapipes/plotting/plotly/simple_plotly.py | 17 ++++++++++++- pandapipes/plotting/plotly/traces.py | 27 ++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/pandapipes/plotting/plotly/simple_plotly.py b/pandapipes/plotting/plotly/simple_plotly.py index 0faee2c8..370b0e8e 100644 --- a/pandapipes/plotting/plotly/simple_plotly.py +++ b/pandapipes/plotting/plotly/simple_plotly.py @@ -5,7 +5,7 @@ import pandas as pd from pandapipes.plotting.plotly.traces import create_junction_trace, create_pipe_trace, \ - create_valve_trace, create_compressor_trace + create_valve_trace, create_compressor_trace, create_press_control_trace from pandapower.plotting.plotly.simple_plotly import _simple_plotly_generic, draw_traces try: @@ -129,15 +129,30 @@ def simple_plotly(net, use_pipe_geodata=None, on_map=False, auto_open=auto_open, showlegend=showlegend) if "valve" in net.keys() and len(net.valve) > 0: + if "source_name" in net.valve.columns: + info = net.valve.apply(lambda x: f"{x['name']}
{x['source_name']}", axis=1) + else: + info = None traces.extend(create_valve_trace(net, valves=net.valve.loc[net.valve.opened].index, size=valve_size, color=valve_color, + infofunc=info, trace_name="open valves")) traces.extend(create_valve_trace(net, valves=net.valve.loc[~net.valve.opened].index, size=valve_size, color=valve_color, dash="dot", + infofunc=info, trace_name="closed valves")) if "compressor" in net.keys() and len(net.compressor) > 0: traces.extend(create_compressor_trace(net, size=compressor_size, color=compressor_color)) + if "press_control" in net.keys() and len(net.press_control) > 0: + traces.extend( + create_press_control_trace(net, size=compressor_size, color="cyan", + trace_name='compressors SPO', + legendgroup='compressors SPO')) + traces.extend(create_junction_trace(net, net.press_control.controlled_junction.values, + color="red", size=10, + trace_name="controlled junction", + legendgroup='compressors SPO')) if additional_traces: if isinstance(additional_traces, dict): traces.append(additional_traces) diff --git a/pandapipes/plotting/plotly/traces.py b/pandapipes/plotting/plotly/traces.py index aa5e029c..8e487114 100644 --- a/pandapipes/plotting/plotly/traces.py +++ b/pandapipes/plotting/plotly/traces.py @@ -85,4 +85,29 @@ def create_compressor_trace(net, compressors=None, use_pipe_geodata=False, size= cmap=cmap, cbar_title=cbar_title, show_colorbar=show_colorbar, cmap_vals=cmap_vals, cmin=cmin, cmax=cmax, cpos=cpos, branch_element=branch_element, separator_element=separator_element, - node_element=node_element, cmap_vals_category="compr_power_mw") \ No newline at end of file + node_element=node_element, cmap_vals_category="compr_power_mw") + + +def create_press_control_trace(net, compressors=None, size=3.0, + color='cyan', infofunc=None, trace_name='pressure controller', + legendgroup='pressure controller'): + branch_element = "press_control" + node_element = "junction" + separator_element = "valve" + respect_valves = False + cmap = None + cbar_title = None + show_colorbar = True + cmap_vals = None + cmin = None + cmax = None + cpos = 1.1 + use_pipe_geodata = False + + return _create_branch_trace(net=net, branches=compressors, use_branch_geodata=use_pipe_geodata, + respect_separators=respect_valves, width=size, color=color, + infofunc=infofunc, trace_name=trace_name, legendgroup=legendgroup, + cmap=cmap, cbar_title=cbar_title, show_colorbar=show_colorbar, + cmap_vals=cmap_vals, cmin=cmin, cmax=cmax, cpos=cpos, + branch_element=branch_element, separator_element=separator_element, + node_element=node_element, cmap_vals_category="controlled_p_bar") From f5356087e1fca8646bf68961ebccafd914c28b00 Mon Sep 17 00:00:00 2001 From: Jolando Kisse Date: Fri, 20 Dec 2024 14:30:46 +0100 Subject: [PATCH 4/4] add pressure control trace (#680) --- pandapipes/plotting/plotly/simple_plotly.py | 17 ++++++++++++- pandapipes/plotting/plotly/traces.py | 27 ++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/pandapipes/plotting/plotly/simple_plotly.py b/pandapipes/plotting/plotly/simple_plotly.py index 0faee2c8..370b0e8e 100644 --- a/pandapipes/plotting/plotly/simple_plotly.py +++ b/pandapipes/plotting/plotly/simple_plotly.py @@ -5,7 +5,7 @@ import pandas as pd from pandapipes.plotting.plotly.traces import create_junction_trace, create_pipe_trace, \ - create_valve_trace, create_compressor_trace + create_valve_trace, create_compressor_trace, create_press_control_trace from pandapower.plotting.plotly.simple_plotly import _simple_plotly_generic, draw_traces try: @@ -129,15 +129,30 @@ def simple_plotly(net, use_pipe_geodata=None, on_map=False, auto_open=auto_open, showlegend=showlegend) if "valve" in net.keys() and len(net.valve) > 0: + if "source_name" in net.valve.columns: + info = net.valve.apply(lambda x: f"{x['name']}
{x['source_name']}", axis=1) + else: + info = None traces.extend(create_valve_trace(net, valves=net.valve.loc[net.valve.opened].index, size=valve_size, color=valve_color, + infofunc=info, trace_name="open valves")) traces.extend(create_valve_trace(net, valves=net.valve.loc[~net.valve.opened].index, size=valve_size, color=valve_color, dash="dot", + infofunc=info, trace_name="closed valves")) if "compressor" in net.keys() and len(net.compressor) > 0: traces.extend(create_compressor_trace(net, size=compressor_size, color=compressor_color)) + if "press_control" in net.keys() and len(net.press_control) > 0: + traces.extend( + create_press_control_trace(net, size=compressor_size, color="cyan", + trace_name='compressors SPO', + legendgroup='compressors SPO')) + traces.extend(create_junction_trace(net, net.press_control.controlled_junction.values, + color="red", size=10, + trace_name="controlled junction", + legendgroup='compressors SPO')) if additional_traces: if isinstance(additional_traces, dict): traces.append(additional_traces) diff --git a/pandapipes/plotting/plotly/traces.py b/pandapipes/plotting/plotly/traces.py index aa5e029c..8e487114 100644 --- a/pandapipes/plotting/plotly/traces.py +++ b/pandapipes/plotting/plotly/traces.py @@ -85,4 +85,29 @@ def create_compressor_trace(net, compressors=None, use_pipe_geodata=False, size= cmap=cmap, cbar_title=cbar_title, show_colorbar=show_colorbar, cmap_vals=cmap_vals, cmin=cmin, cmax=cmax, cpos=cpos, branch_element=branch_element, separator_element=separator_element, - node_element=node_element, cmap_vals_category="compr_power_mw") \ No newline at end of file + node_element=node_element, cmap_vals_category="compr_power_mw") + + +def create_press_control_trace(net, compressors=None, size=3.0, + color='cyan', infofunc=None, trace_name='pressure controller', + legendgroup='pressure controller'): + branch_element = "press_control" + node_element = "junction" + separator_element = "valve" + respect_valves = False + cmap = None + cbar_title = None + show_colorbar = True + cmap_vals = None + cmin = None + cmax = None + cpos = 1.1 + use_pipe_geodata = False + + return _create_branch_trace(net=net, branches=compressors, use_branch_geodata=use_pipe_geodata, + respect_separators=respect_valves, width=size, color=color, + infofunc=infofunc, trace_name=trace_name, legendgroup=legendgroup, + cmap=cmap, cbar_title=cbar_title, show_colorbar=show_colorbar, + cmap_vals=cmap_vals, cmin=cmin, cmax=cmax, cpos=cpos, + branch_element=branch_element, separator_element=separator_element, + node_element=node_element, cmap_vals_category="controlled_p_bar")