Exemple #1
0
def create_edge_center_trace(line_trace,
                             size=1,
                             patch_type="circle",
                             color="grey",
                             infofunc=None,
                             trace_name='edge_center'):
    """
    Creates a plotly trace of pandapower buses.

    INPUT:
        **line traces** (from pandapowerNet) - The already generated line traces with center geodata

    OPTIONAL:

        **size** (int, 5) - patch size

        **patch_type** (str, "circle") - patch type, can be

                - "circle" for a circle
                - "square" for a rectangle
                - "diamond" for a diamond
                - much more pathc types at https://plot.ly/python/reference/#scatter-marker

        **infofunc** (list, None) - hoverinfo for each trace element

        **trace_name** (String, "buses") - name of the trace which will appear in the legend

        **color** (String, "blue") - color of buses in the trace

    """
    color = get_plotly_color(color)

    bus_trace = dict(type='scatter',
                     text=[],
                     mode='markers',
                     hoverinfo='text',
                     name=trace_name,
                     marker=dict(color=color, size=size, symbol=patch_type))

    bus_trace['x'], bus_trace['y'] = (line_trace[0]["x"][1::4],
                                      line_trace[0]["y"][1::4])

    bus_trace['text'] = infofunc

    return [bus_trace]
Exemple #2
0
def create_bus_trace(net,
                     buses=None,
                     size=5,
                     patch_type="circle",
                     color="blue",
                     infofunc=None,
                     trace_name='buses',
                     legendgroup=None,
                     cmap=None,
                     cmap_vals=None,
                     cbar_title=None,
                     cmin=None,
                     cmax=None,
                     colormap_column="vm_pu"):
    """
    Creates a plotly trace of pandapower buses.

    INPUT:
        **net** (pandapowerNet) - The pandapower network

    OPTIONAL:
        **buses** (list, None) - The buses for which the collections are created.
        If None, all buses in the network are considered.

        **size** (int, 5) - patch size

        **patch_type** (str, "circle") - patch type, can be

                - "circle" for a circle
                - "square" for a rectangle
                - "diamond" for a diamond
                - much more pathc types at https://plot.ly/python/reference/#scatter-marker

        **infofunc** (list, None) - hoverinfo for each trace element

        **trace_name** (String, "buses") - name of the trace which will appear in the legend

        **color** (String, "blue") - color of buses in the trace

        **cmap** (String, None) - name of a colormap which exists within plotly (Greys, YlGnBu, Greens, YlOrRd,
        Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis)
        alternatively a custom discrete colormap can be used

        **cmap_vals** (list, None) - values used for coloring using colormap

        **cbar_title** (String, None) - title for the colorbar

        **cmin** (float, None) - colorbar range minimum

        **cmax** (float, None) - colorbar range maximum

        **colormap_column** (str, "vm_pu") - set color of bus according to this variable

    """
    color = get_plotly_color(color)

    bus_trace = dict(type='scatter',
                     text=[],
                     mode='markers',
                     hoverinfo='text',
                     name=trace_name,
                     marker=dict(color=color, size=size, symbol=patch_type))

    buses = net.bus.index.tolist() if buses is None else list(buses)

    buses2plot = net.bus.index.isin(buses)

    buses_with_geodata = net.bus.index.isin(net.bus_geodata.index)
    buses2plot = buses2plot & buses_with_geodata
    bus_plot_index = net.bus.index[buses2plot]

    bus_trace['x'], bus_trace['y'] = (net.bus_geodata.loc[bus_plot_index,
                                                          'x'].tolist(),
                                      net.bus_geodata.loc[bus_plot_index,
                                                          'y'].tolist())

    bus_trace['text'] = net.bus.loc[bus_plot_index,
                                    'name'] if infofunc is None else infofunc

    if legendgroup:
        bus_trace['legendgroup'] = legendgroup

    # if color map is set
    if cmap is not None:
        # TODO introduce discrete colormaps (see contour plots in plotly)
        # if cmap_vals are not given

        cmap = 'Jet' if cmap is True else cmap

        if cmap_vals is not None:
            cmap_vals = cmap_vals
        else:
            if net.res_line.shape[0] == 0:
                logger.error(
                    "There are no power flow results for buses voltage magnitudes which are default for bus "
                    "colormap coloring..."
                    "set cmap_vals input argument if you want colormap according to some specific values..."
                )
            cmap_vals = net.res_bus.loc[bus_plot_index, colormap_column].values

        cmap_vals = net.res_bus.loc[
            bus_plot_index,
            colormap_column] if cmap_vals is None else cmap_vals

        cmin = cmin if cmin else cmap_vals.min()
        cmax = cmax if cmax else cmap_vals.max()

        bus_trace['marker'] = Marker(
            size=size,
            color=cmap_vals,
            cmin=cmin,
            cmax=cmax,
            colorscale=cmap,
            colorbar=ColorBar(thickness=10, x=1.0, titleside='right'),
        )

        if cbar_title:
            bus_trace['marker']['colorbar']['title'] = cbar_title

    return [bus_trace]
Exemple #3
0
def create_trafo_trace(net,
                       trafos=None,
                       color='green',
                       width=5,
                       infofunc=None,
                       cmap=None,
                       trace_name='trafos',
                       cmin=None,
                       cmax=None,
                       cmap_vals=None):
    """
    Creates a plotly trace of pandapower trafos.

    INPUT:
        **net** (pandapowerNet) - The pandapower network

    OPTIONAL:
        **trafos** (list, None) - The trafos for which the collections are created.
        If None, all trafos in the network are considered.

        **width** (int, 5) - line width

        **infofunc** (list, None) - hoverinfo for each line

        **trace_name** (String, "lines") - name of the trace which will appear in the legend

        **color** (String, "green") - color of lines in the trace

        **cmap** (bool, False) - name of a colormap which exists within plotly (Greys, YlGnBu, Greens, YlOrRd,
        Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis)

        **cmap_vals** (list, None) - values used for coloring using colormap

        **cbar_title** (String, None) - title for the colorbar

        **cmin** (float, None) - colorbar range minimum

        **cmax** (float, None) - colorbar range maximum


    """
    color = get_plotly_color(color)

    # defining lines to be plot
    trafos = net.trafo.index.tolist() if trafos is None else list(trafos)
    if len(trafos) == 0:
        return []

    trafo_buses_with_geodata = net.trafo.hv_bus.isin(net.bus_geodata.index) &\
                               net.trafo.lv_bus.isin(net.bus_geodata.index)

    trafos_mask = net.trafo.index.isin(trafos)
    tarfo2plot = net.trafo[trafo_buses_with_geodata & trafos_mask]

    if cmap is not None:
        cmap = 'jet' if cmap is None else cmap

        cmin = 0 if cmin is None else cmin
        cmax = 100 if cmin is None else cmax

        if cmap_vals is not None:
            cmap_vals = cmap_vals
        else:
            if net.res_trafo.shape[0] == 0:
                logger.error(
                    "There are no power flow results for lines which are default for line colormap coloring..."
                    "set cmap_vals input argument if you want colormap according to some specific values..."
                )
            cmap_vals = net.res_trafo.loc[tarfo2plot.index,
                                          'loading_percent'].values

        cmap_colors = get_plotly_cmap(cmap_vals,
                                      cmap_name=cmap,
                                      cmin=cmin,
                                      cmax=cmax)
        trafo_traces = []
        col_i = 0
        for _, trafo in tarfo2plot.iterrows():
            trafo_trace = dict(type='scatter',
                               text=[],
                               line=Line(width=width,
                                         color=cmap_colors[col_i]),
                               hoverinfo='text',
                               mode='lines',
                               name=trace_name)

            trafo_trace['text'] = trafo['name'].tolist(
            ) if infofunc is None else infofunc[col_i]

            from_bus = net.bus_geodata.loc[trafo.hv_bus, 'x']
            to_bus = net.bus_geodata.loc[trafo.lv_bus, 'x']
            trafo_trace['x'] = [from_bus, (from_bus + to_bus) / 2, to_bus]

            from_bus = net.bus_geodata.loc[trafo.hv_bus, 'y']
            to_bus = net.bus_geodata.loc[trafo.lv_bus, 'y']
            trafo_trace['y'] = [from_bus, (from_bus + to_bus) / 2, to_bus]

            trafo_traces.append(trafo_trace)
            col_i += 1

    else:
        trafo_trace = dict(type='scatter',
                           text=[],
                           line=dict(width=width, color=color),
                           hoverinfo='text',
                           mode='lines',
                           name=trace_name)

        trafo_trace['text'] = tarfo2plot['name'].tolist(
        ) if infofunc is None else infofunc

        from_bus = net.bus_geodata.loc[tarfo2plot.hv_bus, 'x'].tolist()
        to_bus = net.bus_geodata.loc[tarfo2plot.lv_bus, 'x'].tolist()
        # center point added because of the hovertool
        center = (np.array(from_bus) + np.array(to_bus)) / 2
        None_list = [None] * len(from_bus)
        trafo_trace['x'] = np.array([from_bus, center, to_bus,
                                     None_list]).T.flatten().tolist()
        trafo_trace['x'] = trafo_trace['x'][:-1]

        from_bus = net.bus_geodata.loc[tarfo2plot.hv_bus, 'y'].tolist()
        to_bus = net.bus_geodata.loc[tarfo2plot.lv_bus, 'y'].tolist()
        # center point added because of the hovertool
        center = (np.array(from_bus) + np.array(to_bus)) / 2
        None_list = [None] * len(from_bus)
        trafo_trace['y'] = np.array([from_bus, center, to_bus,
                                     None_list]).T.flatten().tolist()
        trafo_trace['y'] = trafo_trace['y'][:-1]

        trafo_traces = [trafo_trace]

    return trafo_traces
Exemple #4
0
def create_line_trace(net,
                      lines=None,
                      use_line_geodata=True,
                      respect_switches=False,
                      width=1.0,
                      color='grey',
                      infofunc=None,
                      trace_name='lines',
                      legendgroup=None,
                      cmap=None,
                      cbar_title=None,
                      show_colorbar=True,
                      cmap_vals=None,
                      cmin=None,
                      cmax=None):
    """
    Creates a plotly trace of pandapower lines.

    INPUT:
        **net** (pandapowerNet) - The pandapower network

    OPTIONAL:
        **lines** (list, None) - The lines for which the collections are created.
        If None, all lines in the network are considered.

        **width** (int, 1) - line width

        **respect_switches** (bool, False) - flag for consideration of disconnected lines

        **infofunc** (list, None) - hoverinfo for each line

        **trace_name** (String, "lines") - name of the trace which will appear in the legend

        **color** (String, "grey") - color of lines in the trace

        **legendgroup** (String, None) - defines groups of layers that will be displayed in a legend
        e.g. groups according to voltage level (as used in `vlevel_plotly`)

        **cmap** (String, None) - name of a colormap which exists within plotly if set to True default `Jet`
        colormap is used, alternative colormaps : Greys, YlGnBu, Greens, YlOrRd,
        Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis

        **cmap_vals** (list, None) - values used for coloring using colormap

        **show_colorbar** (bool, False) - flag for showing or not corresponding colorbar

        **cbar_title** (String, None) - title for the colorbar

        **cmin** (float, None) - colorbar range minimum

        **cmax** (float, None) - colorbar range maximum

        """

    color = get_plotly_color(color)

    # defining lines to be plot
    lines = net.line.index.tolist() if lines is None else list(lines)
    if len(lines) == 0:
        return []

    nogolines = set()
    if respect_switches:
        nogolines = set(net.switch.element[(net.switch.et == "l")
                                           & (net.switch.closed == 0)])
    nogolines_mask = net.line.index.isin(nogolines)

    lines_mask = net.line.index.isin(lines)
    lines2plot_mask = ~nogolines_mask & lines_mask
    lines2plot = net.line[lines2plot_mask]

    use_line_geodata = use_line_geodata if net.line_geodata.shape[
        0] > 0 else False
    if use_line_geodata:
        lines_with_geodata = lines2plot.index.isin(net.line_geodata.index)
        lines2plot = lines2plot[lines_with_geodata]
    else:
        lines_with_geodata = lines2plot.from_bus.isin(net.bus_geodata.index) & \
                             lines2plot.to_bus.isin(net.bus_geodata.index)
        lines2plot = lines2plot[lines_with_geodata]

    if cmap is not None:
        # workaround: if colormap plot is used, each line need to be separate scatter object because
        # plotly still doesn't support appropriately colormap for line objects
        # TODO correct this when plotly solves existing github issue about Line colorbar

        cmap = 'jet' if cmap is True else cmap

        if cmap_vals is not None:
            cmap_vals = cmap_vals
        else:
            if net.res_line.shape[0] == 0:
                logger.error(
                    "There are no power flow results for lines which are default for line colormap coloring..."
                    "set cmap_vals input argument if you want colormap according to some specific values..."
                )
            cmap_vals = net.res_line.loc[lines2plot.index,
                                         'loading_percent'].values

        cmap_lines = get_plotly_cmap(cmap_vals,
                                     cmap_name=cmap,
                                     cmin=cmin,
                                     cmax=cmax)
        cmap_lines = list(compress(
            cmap_lines, lines2plot_mask))  # select with mask from cmap_lines
        if infofunc is not None:
            infofunc = list(compress(infofunc, lines2plot_mask))

        line_traces = []
        col_i = 0
        for idx, line in lines2plot.iterrows():
            line_trace = dict(type='scatter',
                              text=[],
                              hoverinfo='text',
                              mode='lines',
                              name=trace_name,
                              line=Line(width=width, color=color))

            line_trace['x'], line_trace['y'] = _get_line_geodata_plotly(
                net, lines2plot.loc[idx:idx], use_line_geodata)

            line_trace['line']['color'] = cmap_lines[col_i]

            line_trace[
                'text'] = line['name'] if infofunc is None else infofunc[col_i]

            line_traces.append(line_trace)
            col_i += 1

        cmin = cmin if cmin else cmap_vals.min()
        cmax = cmax if cmax else cmap_vals.max()

        if show_colorbar:
            try:
                # TODO for custom colormaps
                cbar_cmap_name = 'Jet' if cmap is 'jet' else cmap
                # workaround to get colorbar for lines (an unvisible node is added)
                lines_cbar = dict(type='scatter',
                                  x=[net.bus_geodata.x[0]],
                                  y=[net.bus_geodata.y[0]],
                                  mode='markers',
                                  marker=Marker(
                                      size=0,
                                      cmin=cmin,
                                      cmax=cmax,
                                      color='rgb(255,255,255)',
                                      colorscale=cbar_cmap_name,
                                      colorbar=ColorBar(thickness=10,
                                                        x=1.1,
                                                        titleside='right'),
                                  ))
                if cbar_title:
                    lines_cbar['marker']['colorbar']['title'] = cbar_title

                line_traces.append(lines_cbar)
            except:
                pass

    else:
        line_trace = dict(type='scatter',
                          text=[],
                          hoverinfo='text',
                          mode='lines',
                          name=trace_name,
                          line=Line(width=width, color=color))

        line_trace['x'], line_trace['y'] = _get_line_geodata_plotly(
            net, lines2plot, use_line_geodata)

        line_trace['text'] = lines2plot['name'].tolist(
        ) if infofunc is None else infofunc

        if legendgroup:
            line_trace['legendgroup'] = legendgroup

        line_traces = [line_trace]

    if len(nogolines) > 0:
        line_trace = dict(type='scatter',
                          text=[],
                          hoverinfo='text',
                          mode='lines',
                          name='disconnected lines',
                          line=Line(width=width / 2, color='grey', dash='dot'))

        lines2plot = net.line.loc[nogolines]

        line_trace['x'], line_trace['y'] = _get_line_geodata_plotly(
            net, lines2plot, use_line_geodata)

        line_trace['text'] = lines2plot['name'].tolist()

        if legendgroup:
            line_trace['legendgroup'] = legendgroup

        line_traces.append(line_trace)
    return line_traces
Exemple #5
0
def create_trafo_trace(net,
                       trafos=None,
                       color='green',
                       width=5,
                       infofunc=None,
                       cmap=None,
                       trace_name='trafos',
                       cmin=None,
                       cmax=None,
                       cmap_vals=None,
                       use_line_geodata=None):
    """
    Creates a plotly trace of pandapower trafos.

    INPUT:
        **net** (pandapowerNet) - The pandapower network

    OPTIONAL:
        **trafos** (list, None) - The trafos for which the collections are created.
        If None, all trafos in the network are considered.

        **width** (int, 5) - line width

        **infofunc** (pd.Series, None) - hoverinfo for trafo elements. Indices should correspond
            to the pandapower element indices

        **trace_name** (String, "lines") - name of the trace which will appear in the legend

        **color** (String, "green") - color of lines in the trace

        **cmap** (bool, False) - name of a colormap which exists within plotly (Greys, YlGnBu,
            Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot,
            Blackbody, Earth, Electric, Viridis)

        **cmap_vals** (list, None) - values used for coloring using colormap

        **cbar_title** (String, None) - title for the colorbar

        **cmin** (float, None) - colorbar range minimum

        **cmax** (float, None) - colorbar range maximum


    """
    color = get_plotly_color(color)

    # defining lines to be plot
    trafos = net.trafo.index.tolist() if trafos is None else list(trafos)
    if len(trafos) == 0:
        return []

    trafo_buses_with_geodata = net.trafo.hv_bus.isin(net.bus_geodata.index) & \
        net.trafo.lv_bus.isin(net.bus_geodata.index)

    trafos_mask = net.trafo.index.isin(trafos)
    trafos_to_plot = net.trafo[trafo_buses_with_geodata & trafos_mask]

    if infofunc is not None:
        if not isinstance(infofunc, pd.Series) and isinstance(infofunc, Iterable) and \
                len(infofunc) == len(trafos):
            infofunc = pd.Series(index=trafos, data=infofunc)
        assert isinstance(infofunc, pd.Series), \
            "infofunc should be a pandas series with the net.trafo.index to the infofunc contents"
        infofunc = infofunc.loc[trafos_to_plot.index]

    cmap_colors = []
    if cmap is not None:
        cmap = 'jet' if cmap is None else cmap

        cmin = 0 if cmin is None else cmin
        cmax = 100 if cmin is None else cmax

        if cmap_vals is not None:
            cmap_vals = cmap_vals
        else:
            if net.res_trafo.shape[0] == 0:
                logger.error(
                    "There are no power flow results for lines which are default for line colormap coloring..."
                    "set cmap_vals input argument if you want colormap according to some specific values..."
                )
            cmap_vals = net.res_trafo.loc[trafos_to_plot.index,
                                          'loading_percent'].values

        cmap_colors = get_plotly_cmap(cmap_vals,
                                      cmap_name=cmap,
                                      cmin=cmin,
                                      cmax=cmax)

    trafo_traces = []
    for col_i, (idx, trafo) in enumerate(trafos_to_plot.iterrows()):
        if cmap is not None:
            color = cmap_colors[col_i]

        trafo_trace = dict(type='scatter',
                           text=[],
                           line=Line(width=width, color=color),
                           hoverinfo='text',
                           mode='lines',
                           name=trace_name)

        trafo_trace[
            'text'] = trafo['name'] if infofunc is None else infofunc.loc[idx]

        from_bus = net.bus_geodata.loc[trafo.hv_bus, 'x']
        to_bus = net.bus_geodata.loc[trafo.lv_bus, 'x']
        trafo_trace['x'] = [from_bus, (from_bus + to_bus) / 2, to_bus]

        from_bus = net.bus_geodata.loc[trafo.hv_bus, 'y']
        to_bus = net.bus_geodata.loc[trafo.lv_bus, 'y']
        trafo_trace['y'] = [from_bus, (from_bus + to_bus) / 2, to_bus]

        trafo_traces.append(trafo_trace)

    center_trace = create_edge_center_trace(trafo_traces,
                                            color=color,
                                            infofunc=infofunc,
                                            use_line_geodata=use_line_geodata)
    trafo_traces.append(center_trace)
    return trafo_traces
Exemple #6
0
def create_line_trace(net,
                      lines=None,
                      use_line_geodata=True,
                      respect_switches=False,
                      width=1.0,
                      color='grey',
                      infofunc=None,
                      trace_name='lines',
                      legendgroup=None,
                      cmap=None,
                      cbar_title=None,
                      show_colorbar=True,
                      cmap_vals=None,
                      cmin=None,
                      cmax=None,
                      cpos=1.1):
    """
    Creates a plotly trace of pandapower lines.

    INPUT:
        **net** (pandapowerNet) - The pandapower network

    OPTIONAL:
        **lines** (list, None) - The lines for which the collections are created.
        If None, all lines in the network are considered.

        **width** (int, 1) - line width

        **respect_switches** (bool, False) - flag for consideration of disconnected lines

        **infofunc** (pd.Series, None) - hoverinfo for line elements. Indices should correspond to
            the pandapower element indices

        **trace_name** (String, "lines") - name of the trace which will appear in the legend

        **color** (String, "grey") - color of lines in the trace

        **legendgroup** (String, None) - defines groups of layers that will be displayed in a legend
        e.g. groups according to voltage level (as used in `vlevel_plotly`)

        **cmap** (String, None) - name of a colormap which exists within plotly if set to True default `Jet`
        colormap is used, alternative colormaps : Greys, YlGnBu, Greens, YlOrRd,
        Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis

        **cmap_vals** (list, None) - values used for coloring using colormap

        **show_colorbar** (bool, False) - flag for showing or not corresponding colorbar

        **cbar_title** (String, None) - title for the colorbar

        **cmin** (float, None) - colorbar range minimum

        **cmax** (float, None) - colorbar range maximum

        **cpos** (float, 1.1) - position of the colorbar

        """

    color = get_plotly_color(color)

    # defining lines to be plot
    lines = net.line.index.tolist() if lines is None else list(lines)
    if len(lines) == 0:
        return []

    if infofunc is not None:
        if not isinstance(infofunc, pd.Series) and isinstance(infofunc, Iterable) and \
                len(infofunc) == len(lines):
            infofunc = pd.Series(index=lines, data=infofunc)
        if len(infofunc) != len(lines) and len(infofunc) != len(net.line):
            raise UserWarning(
                "Different amount of hover info than lines to plot")
        assert isinstance(infofunc, pd.Series), \
            "infofunc should be a pandas series with the net.line.index to the infofunc contents"

    no_go_lines = set()
    if respect_switches:
        no_go_lines = set(lines) & set(net.switch.element[
            (net.switch.et == "l") & (net.switch.closed == 0)])

    lines_to_plot = net.line.loc[set(net.line.index)
                                 & (set(lines) - no_go_lines)]
    no_go_lines_to_plot = None
    use_line_geodata = use_line_geodata if net.line_geodata.shape[
        0] > 0 else False

    if use_line_geodata:
        lines_to_plot = lines_to_plot.loc[set(lines_to_plot.index)
                                          & set(net.line_geodata.index)]
    else:
        lines_with_geodata = lines_to_plot.from_bus.isin(net.bus_geodata.index) & \
                             lines_to_plot.to_bus.isin(net.bus_geodata.index)
        lines_to_plot = lines_to_plot.loc[lines_with_geodata]

    cmap_lines = None
    if cmap is not None:
        # workaround: if colormap plot is used, each line need to be separate scatter object because
        # plotly still doesn't support appropriately colormap for line objects
        # TODO correct this when plotly solves existing github issue about Line colorbar

        cmap = 'jet' if cmap is True else cmap

        if cmap_vals is not None:
            if not isinstance(cmap_vals, np.ndarray):
                cmap_vals = np.asarray(cmap_vals)
        else:
            if net.res_line.shape[0] == 0:
                logger.error(
                    "There are no power flow results for lines which are default for line colormap coloring..."
                    "set cmap_vals input argument if you want colormap according to some specific values..."
                )
            cmap_vals = net.res_line.loc[lines_to_plot.index,
                                         'loading_percent'].values

        cmap_lines = get_plotly_cmap(cmap_vals,
                                     cmap_name=cmap,
                                     cmin=cmin,
                                     cmax=cmax)
        if len(cmap_lines) == len(net.line):
            # some lines are not plotted although cmap_value were provided for all lines
            line_idx_map = dict(
                zip(net.line.loc[lines].index.tolist(), range(len(lines))))
            cmap_lines = [
                cmap_lines[line_idx_map[idx]] for idx in lines_to_plot.index
            ]
        else:
            assert len(cmap_lines) == len(lines_to_plot), \
                "Different amounts of cmap values and lines to plot were supplied"

    line_traces = []
    for col_i, (idx, line) in enumerate(lines_to_plot.iterrows()):
        line_color = color
        line_info = line['name']
        if cmap is not None:
            try:
                line_color = cmap_lines[col_i]
                line_info = line['name'] if infofunc is None else infofunc.loc[
                    idx]
            except IndexError:
                logger.warning(
                    "No color and info for line {:d} (name: {}) available".
                    format(idx, line['name']))

        line_trace = dict(type='scatter',
                          text=[],
                          hoverinfo='text',
                          mode='lines',
                          name=trace_name,
                          line=Line(width=width, color=color))

        line_trace['x'], line_trace['y'] = _get_line_geodata_plotly(
            net, lines_to_plot.loc[idx:idx], use_line_geodata)

        line_trace['line']['color'] = line_color

        line_trace['text'] = line_info

        line_traces.append(line_trace)

    if show_colorbar and cmap is not None:

        cmin = cmap_vals.min() if cmin is None else cmin
        cmax = cmap_vals.max() if cmax is None else cmax
        try:
            # TODO for custom colormaps
            cbar_cmap_name = 'Jet' if cmap == 'jet' else cmap
            # workaround to get colorbar for lines (an unvisible node is added)
            # get x and y of first line.from_bus:
            x = [net.bus_geodata.x[net.line.from_bus[net.line.index[0]]]]
            y = [net.bus_geodata.y[net.line.from_bus[net.line.index[0]]]]
            lines_cbar = dict(type='scatter',
                              x=x,
                              y=y,
                              mode='markers',
                              marker=Marker(
                                  size=0,
                                  cmin=cmin,
                                  cmax=cmax,
                                  color='rgb(255,255,255)',
                                  opacity=0,
                                  colorscale=cbar_cmap_name,
                                  colorbar=ColorBar(thickness=10, x=cpos),
                              ))
            if cbar_title:
                lines_cbar['marker']['colorbar']['title'] = cbar_title

            lines_cbar['marker']['colorbar']['title']['side'] = 'right'

            line_traces.append(lines_cbar)
        except:
            pass

    if len(no_go_lines) > 0:
        no_go_lines_to_plot = net.line.loc[no_go_lines]
        for idx, line in no_go_lines_to_plot.iterrows():
            line_color = color
            line_trace = dict(type='scatter',
                              text=[],
                              hoverinfo='text',
                              mode='lines',
                              name='disconnected lines',
                              line=Line(width=width / 2,
                                        color='grey',
                                        dash='dot'))

            line_trace['x'], line_trace['y'] = _get_line_geodata_plotly(
                net, no_go_lines_to_plot.loc[idx:idx], use_line_geodata)

            line_trace['line']['color'] = line_color
            try:
                line_trace['text'] = infofunc.loc[idx]
            except (KeyError, IndexError, AttributeError):
                line_trace["text"] = line['name']

            line_traces.append(line_trace)

            if legendgroup:
                line_trace['legendgroup'] = legendgroup

    # sort infofunc so that it is the correct order lines_to_plot + no_go_lines_to_plot
    if infofunc is not None:
        if not isinstance(infofunc, pd.Series) and isinstance(infofunc, Iterable) and \
                len(infofunc) == len(net.line):
            infofunc = pd.Series(index=net.line.index, data=infofunc)
        assert isinstance(infofunc, pd.Series), \
            "infofunc should be a pandas series with the net.line.index to the infofunc contents"
        sorted_idx = lines_to_plot.index.tolist()
        if no_go_lines_to_plot is not None:
            sorted_idx += no_go_lines_to_plot.index.tolist()
        infofunc = infofunc.loc[sorted_idx]

    center_trace = create_edge_center_trace(line_traces,
                                            color=color,
                                            infofunc=infofunc,
                                            use_line_geodata=use_line_geodata)
    line_traces.append(center_trace)
    return line_traces
Exemple #7
0
def _create_branch_trace(net,
                         branches=None,
                         use_branch_geodata=True,
                         respect_separators=False,
                         width=1.0,
                         color='grey',
                         infofunc=None,
                         trace_name='lines',
                         legendgroup=None,
                         cmap=None,
                         cbar_title=None,
                         show_colorbar=True,
                         cmap_vals=None,
                         cmin=None,
                         cmax=None,
                         cpos=1.1,
                         branch_element='line',
                         separator_element='switch',
                         node_element='bus',
                         cmap_vals_category='loading_percent'):
    """
   Creates a plotly trace of branch elements. The rather generic, non-power net specific names
   were introduced to make it usable in other packages, e.g. for pipe networks.

   INPUT:
       **net** (pandapowerNet) - The  network

   OPTIONAL:
       **branches** (list, None) - The branches for which the collections are created.
                                   If None, all branches in the network are considered.

       **use_branch_geodata** (bool, True) - whether the geodata of the branch tables should be used

       **respect_separators** (bool, True) - whether separating elements like switches should be
                                             considered

       **width** (int, 1) - branch width

       **color** (String, "grey") - color of lines in the trace

       **infofunc** (pd.Series, None) - hoverinfo for line elements. Indices should correspond to
           the pandapower element indices

       **trace_name** (String, "lines") - name of the trace which will appear in the legend

       **legendgroup** (String, None) - defines groups of layers that will be displayed in a legend
       e.g. groups according to voltage level (as used in `vlevel_plotly`)

       **cmap** (String, None) - name of a colormap which exists within plotly if set to True default `Jet`
       colormap is used, alternative colormaps : Greys, YlGnBu, Greens, YlOrRd,
       Bluered, RdBu, Reds, Blues, Picnic, Rainbow, Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis

       **cmap_vals** (list, None) - values used for coloring using colormap

       **show_colorbar** (bool, False) - flag for showing or not corresponding colorbar

       **cbar_title** (String, None) - title for the colorbar

       **cmin** (float, None) - colorbar range minimum

       **cmax** (float, None) - colorbar range maximum

       **cpos** (float, 1.1) - position of the colorbar

       **branch_element** (str, "line") - name of the branch element in the net. In a pandapower
                                          net, this is alwas "line"

       **separator_element** (str, "switch") - name of the separator element in the net. In a
                                               pandapower net, this is alwas "switch"

      **node_element** (str, "bus") - name of the node element in the net. In a pandapower net,
                                      this is alwas "bus" (net.bus)

       """

    color = get_plotly_color(color)

    # defining branches (lines) to be plot
    branches = net[branch_element].index.tolist(
    ) if branches is None else list(branches)
    if len(branches) == 0:
        return []

    if infofunc is not None:
        if not isinstance(infofunc, pd.Series) and isinstance(infofunc, Iterable) and \
                len(infofunc) == len(branches):
            infofunc = pd.Series(index=branches, data=infofunc)
        if len(infofunc) != len(branches) and len(infofunc) != len(
                net[branch_element]):
            raise UserWarning("Different amount of hover info than {}s to "
                              "plot".format(branch_element))
        assert isinstance(infofunc, pd.Series), \
            "infofunc should be a pandas series with the net.{}.index to the infofunc " \
            "contents".format(branch_element)
    no_go_branches = set()
    if respect_separators:
        if separator_element == "switch":
            no_go_branches = set(branches) & \
                             set(net[separator_element].element[(net[separator_element].et == "l") &
                                                             (net[separator_element].closed == 0)])
        elif separator_element == "valve":
            no_go_branches = set(branches) & \
                             set(net[separator_element][(~net[separator_element].in_service) |
                                                        (net[separator_element].opened)])
        else:
            raise NotImplementedError(
                "respect separtors is only implements for switches, "
                "not for {}s.".format(separator_element))
    branches_to_plot = net[branch_element].loc[set(net[branch_element].index)
                                               & (set(branches) -
                                                  no_go_branches)]
    no_go_branches_to_plot = None
    branch_geodata = branch_element + "_geodata"
    node_geodata = node_element + "_geodata"
    use_branch_geodata = use_branch_geodata if net[branch_geodata].shape[
        0] > 0 else False
    if use_branch_geodata:
        branches_to_plot = branches_to_plot.loc[
            set(branches_to_plot.index) & set(net[branch_geodata].index)]
    else:
        branches_with_geodata = branches_to_plot['from_'+node_element].isin(
                                                    net[node_geodata].index) & \
                                branches_to_plot['to_'+node_element].isin(net[node_geodata].index)
        branches_to_plot = branches_to_plot.loc[branches_with_geodata]
    cmap_branches = None
    if cmap is not None:
        # workaround: if colormap plot is used, each line need to be separate scatter object because
        # plotly still doesn't support appropriately colormap for line objects
        # TODO correct this when plotly solves existing github issue about Line colorbar

        cmap = 'jet' if cmap is True else cmap

        if cmap_vals is not None:
            if not isinstance(cmap_vals, np.ndarray):
                cmap_vals = np.asarray(cmap_vals)
        else:
            if net['res_' + branch_element].shape[0] == 0:
                logger.error(
                    "There are no simulation results for branches which are default for {}"
                    "colormap coloring..."
                    "set cmap_vals input argument if you want colormap according to some specific "
                    "values...".format(branch_element))
            cmap_vals = net['res_' +
                            branch_element].loc[branches_to_plot.index,
                                                cmap_vals_category].values

        cmap_branches = get_plotly_cmap(cmap_vals,
                                        cmap_name=cmap,
                                        cmin=cmin,
                                        cmax=cmax)
        if len(cmap_branches) == len(net[branch_element]):
            # some branches are not plotted although cmap_value were provided for all branches
            branch_idx_map = dict(
                zip(net[branch_element].loc[branches].index.tolist(),
                    range(len(branches))))
            cmap_branches = [
                cmap_branches[branch_idx_map[idx]]
                for idx in branches_to_plot.index
            ]
        else:
            assert len(cmap_branches) == len(branches_to_plot), \
                "Different amounts of cmap values and branches to plot were supplied"
    branch_traces = []
    for col_i, (idx, branch) in enumerate(branches_to_plot.iterrows()):
        line_color = color
        line_info = branch['name']
        if cmap is not None:
            try:
                line_color = cmap_branches[col_i]
                line_info = branch[
                    'name'] if infofunc is None else infofunc.loc[idx]
            except IndexError:
                logger.warning(
                    "No color and info for {} {:d} (name: {}) available".
                    format(branch_element, idx, branch['name']))

        line_trace = dict(type='scatter',
                          text=[],
                          hoverinfo='text',
                          mode='lines',
                          name=trace_name,
                          line=Line(width=width, color=color))

        line_trace['x'], line_trace['y'] = _get_branch_geodata_plotly(
            net, branches_to_plot.loc[idx:idx], use_branch_geodata,
            branch_element, node_element)

        line_trace['line']['color'] = line_color

        line_trace['text'] = line_info

        branch_traces.append(line_trace)
    if show_colorbar and cmap is not None:

        cmin = cmap_vals.min() if cmin is None else cmin
        cmax = cmap_vals.max() if cmax is None else cmax
        try:
            # TODO for custom colormaps
            cbar_cmap_name = 'Jet' if cmap == 'jet' else cmap
            # workaround to get colorbar for branches (an unvisible node is added)
            # get x and y of first line.from_bus:
            x = [
                net[node_geodata].x[net[branch_element]["from_" + node_element]
                                    [net[branch_element].index[0]]]
            ]
            y = [
                net[node_geodata].y[net[branch_element]["from_" + node_element]
                                    [net[branch_element].index[0]]]
            ]
            branches_cbar = dict(type='scatter',
                                 x=x,
                                 y=y,
                                 mode='markers',
                                 marker=Marker(
                                     size=0,
                                     cmin=cmin,
                                     cmax=cmax,
                                     color='rgb(255,255,255)',
                                     opacity=0,
                                     colorscale=cbar_cmap_name,
                                     colorbar=ColorBar(thickness=10, x=cpos),
                                 ))
            if cbar_title:
                branches_cbar['marker']['colorbar']['title'] = cbar_title

            branches_cbar['marker']['colorbar']['title']['side'] = 'right'

            branch_traces.append(branches_cbar)
        except:
            pass
    if len(no_go_branches) > 0:
        no_go_branches_to_plot = net[branch_element].loc[no_go_branches]
        for idx, branch in no_go_branches_to_plot.iterrows():
            line_color = color
            line_trace = dict(type='scatter',
                              text=[],
                              hoverinfo='text',
                              mode='lines',
                              name='disconnected branches',
                              line=Line(width=width / 2,
                                        color='grey',
                                        dash='dot'))

            line_trace['x'], line_trace['y'] = _get_branch_geodata_plotly(
                net, no_go_branches_to_plot.loc[idx:idx], use_branch_geodata,
                branch_element, node_element)

            line_trace['line']['color'] = line_color
            try:
                line_trace['text'] = infofunc.loc[idx]
            except (KeyError, IndexError, AttributeError):
                line_trace["text"] = branch['name']

            branch_traces.append(line_trace)

            if legendgroup:
                line_trace['legendgroup'] = legendgroup
    # sort infofunc so that it is the correct order lines_to_plot + no_go_lines_to_plot
    if infofunc is not None:
        if not isinstance(infofunc, pd.Series) and isinstance(infofunc, Iterable) and \
                len(infofunc) == len(net[branch_element]):
            infofunc = pd.Series(index=net[branch_element].index,
                                 data=infofunc)
        assert isinstance(infofunc, pd.Series), \
            "infofunc should be a pandas series with the net.{}.index to the infofunc contents" \
            .format(branch_element)
        sorted_idx = branches_to_plot.index.tolist()
        if no_go_branches_to_plot is not None:
            sorted_idx += no_go_branches_to_plot.index.tolist()
        infofunc = infofunc.loc[sorted_idx]
    center_trace = create_edge_center_trace(
        branch_traces,
        color=color,
        infofunc=infofunc,
        use_line_geodata=use_branch_geodata)
    branch_traces.append(center_trace)
    return branch_traces
Exemple #8
0
def _create_node_trace(net,
                       nodes=None,
                       size=5,
                       patch_type='circle',
                       color='blue',
                       infofunc=None,
                       trace_name='nodes',
                       legendgroup=None,
                       cmap=None,
                       cmap_vals=None,
                       cbar_title=None,
                       cmin=None,
                       cmax=None,
                       cpos=1.0,
                       colormap_column='vm_pu',
                       node_element='bus',
                       branch_element='line'):
    """
    Creates a plotly trace of node elements. In pandapower, it should be called by
    create_bus_traces. The rather generic, non-power net specific names were introduced to make it
    usable in other packages, e.g. for pipe networks.

    INPUT:
        **net** (pandapowerNet) - The network

    OPTIONAL:
        **nodes** (list, None) - The nodes for which the collections are created.
                                 If None, all nodes in the network are considered.

        **size** (int, 5) - patch size

        **patch_type** (str, "circle") - patch type, can be

                - "circle" for a circle
                - "square" for a rectangle
                - "diamond" for a diamond
                - much more pathc types at https://plot.ly/python/reference/#scatter-marker

        **infofunc** (pd.Series, None) - hoverinfo for node elements. Indices should correspond to
                                         the node element indices

        **trace_name** (String, "buses") - name of the trace which will appear in the legend

        **color** (String, "blue") - color of nodes in the trace

        **cmap** (String, None) - name of a colormap which exists within plotly
            (Greys, YlGnBu, Greens, YlOrRd, Bluered, RdBu, Reds, Blues, Picnic, Rainbow,
            Portland, Jet, Hot, Blackbody, Earth, Electric, Viridis) alternatively a custom
            discrete colormap can be used

        **cmap_vals** (list, None) - values used for coloring using colormap

        **cbar_title** (String, None) - title for the colorbar

        **cmin** (float, None) - colorbar range minimum

        **cmax** (float, None) - colorbar range maximum

        **cpos** (float, 1.1) - position of the colorbar

        **colormap_column** (str, "vm_pu") - set color of bus according to this variable

        **node_element** (str, "bus") - name of the node element in the net. In a pandapower net,
                                        this is alwas "bus"

        **branch_element** (str, "line") - name of the branch element in the net. In a pandapower
                                           net, this is alwas "line"

    """
    color = get_plotly_color(color)
    node_trace = dict(type='scatter',
                      text=[],
                      mode='markers',
                      hoverinfo='text',
                      name=trace_name,
                      marker=dict(color=color, size=size, symbol=patch_type))
    nodes = net[node_element].index.tolist() if nodes is None else list(nodes)
    node_geodata = node_element + "_geodata"
    node_plot_index = [
        b for b in nodes
        if b in list(set(nodes) & set(net[node_geodata].index))
    ]
    node_trace['x'], node_trace['y'] = \
        (net[node_geodata].loc[node_plot_index, 'x'].tolist(),
         net[node_geodata].loc[node_plot_index, 'y'].tolist())
    if not isinstance(infofunc, pd.Series) and isinstance(infofunc, Iterable) and \
            len(infofunc) == len(nodes):
        infofunc = pd.Series(index=nodes, data=infofunc)
    node_trace['text'] = net[node_element].loc[node_plot_index, 'name'] if infofunc is None else \
        infofunc.loc[nodes]
    if legendgroup:
        node_trace['legendgroup'] = legendgroup
    # if color map is set
    if cmap is not None:
        # TODO introduce discrete colormaps (see contour plots in plotly)
        # if cmap_vals are not given

        cmap = 'Jet' if cmap is True else cmap

        if cmap_vals is not None:
            cmap_vals = cmap_vals
        else:
            if net["res_" + branch_element].shape[0] == 0:
                if branch_element == "line":
                    logger.error(
                        "There are no power flow results for buses voltage magnitudes which are"
                        "default for bus colormap coloring..."
                        "set cmap_vals input argument if you want colormap according to some "
                        "specific values...")
                else:
                    logger.error(
                        "There are no simulation results which are default for %s colormap coloring..."
                        "set cmap_vals input argument if you want colormap according to some "
                        "specific values..." % node_element)
            cmap_vals = net["res_" + node_element].loc[node_plot_index,
                                                       colormap_column].values

        cmap_vals = net["res_" + node_element].loc[
            node_plot_index,
            colormap_column] if cmap_vals is None else cmap_vals

        cmin = cmap_vals.min() if cmin is None else cmin
        cmax = cmap_vals.max() if cmax is None else cmax

        node_trace['marker'] = Marker(size=size,
                                      color=cmap_vals,
                                      cmin=cmin,
                                      cmax=cmax,
                                      colorscale=cmap,
                                      colorbar=ColorBar(thickness=10, x=cpos),
                                      symbol=patch_type)

        if cbar_title:
            node_trace['marker']['colorbar']['title'] = cbar_title

        node_trace['marker']['colorbar']['title']['side'] = 'right'
    return [node_trace]