def test_connected_components(feeder_network):
    net = feeder_network
    mg = top.create_nxgraph(net)
    cc = top.connected_components(mg)
    assert list(cc) == [{0, 1, 2, 3}]
    cc_notrav = top.connected_components(mg, notravbuses={0, 2})
    assert list(cc_notrav) == [{0, 1, 2}, {0, 2, 3}]
Beispiel #2
0
def fuse_geodata(net):
    mg = top.create_nxgraph(net, include_lines=False, respect_switches=False)
    geocoords = set(net.bus_geodata.index)
    for area in top.connected_components(mg):
        if len(area & geocoords) > 1:
            geo = net.bus_geodata.loc[area & geocoords].values[0]
            for bus in area:
                net.bus_geodata.loc[bus] = geo
Beispiel #3
0
def plot_feeder():
    net = nw.case118()
    fig, ax = plt.subplots(1, 1)
    mg = top.create_nxgraph(net, nogobuses=set(net.trafo.lv_bus.values))
    colors = sns.color_palette()
    collections = list()
    sizes = pplt.get_collection_sizes(net)
    voltage_levels = net.bus.vn_kv.unique()
    voltage_level_colors = dict(zip(voltage_levels, colors))
    legend_entries = dict()
    gens = set(net.gen.loc[:, "bus"].values)
    for area, color in zip(top.connected_components(mg), colors):
        vn_area = net.bus.loc[list(area)[0], "vn_kv"]
        color = voltage_level_colors[vn_area]
        legend_entries[vn_area] = color
        area_gens = gens - area
        other = area - gens

        collections.append(
            pplt.create_bus_collection(net,
                                       area_gens,
                                       color=color,
                                       size=sizes["bus"],
                                       zorder=11,
                                       patch_type="rect"))
        collections.append(
            pplt.create_bus_collection(net,
                                       other,
                                       color=color,
                                       size=sizes["bus"],
                                       zorder=11))
        line_ind = net.line.loc[:, "from_bus"].isin(
            area) | net.line.loc[:, "to_bus"].isin(area)
        lines = net.line.loc[line_ind].index
        collections.append(pplt.create_line_collection(net, lines,
                                                       color=color))

    eg_vn = net.bus.at[net.ext_grid.bus.values[0], "vn_kv"]
    collections.append(
        pplt.create_ext_grid_collection(net,
                                        size=sizes["ext_grid"],
                                        color=voltage_level_colors[eg_vn]))
    collections.append(
        pplt.create_trafo_collection(net, size=sizes["trafo"], zorder=1))
    pplt.draw_collections(collections, ax=ax)
    custom_legend(fig, entries=legend_entries)
    legend_entries = {"gen": "grey"}
    custom_legend(fig, entries=legend_entries, loc='center right', marker="s")
    print_info(net, fig)
    plt.show()
        index=net.bus.index)
    return bgd


if __name__ == "__main__":
    import pandapower as pp
    import pandapower.networks as nw
    import pandas as pd
    import networkx as nx
    import plotting

    net = nw.mv_oberrhein()
    pp.runpp(net)
    mg = top.create_nxgraph(net, respect_switches=True)
    feeders = list(
        top.connected_components(mg, notravbuses=set(net.trafo.lv_bus.values)))
    lines_with_open_switches = set(
        net.switch.query("not closed and et == 'l'").element.values)

    fig, axs = plt.subplots(2)
    for bgd, ax in zip(
        [net.bus_geodata, voltage_profile_to_bus_geodata(net)], axs):
        for color, f in zip(["C0", "C1", "C2", "C3"], feeders):
            l = set(net.line.index[net.line.from_bus.isin(
                f)]) - lines_with_open_switches
            c = plotting.create_line_collection(net,
                                                lines=l,
                                                use_bus_geodata=True,
                                                color=color,
                                                bus_geodata=bgd)
            ax.add_collection(c)
Beispiel #5
0
def disconnected_elements(net):
    """
    Checks, if there are network sections without a connection to an ext_grid. Returns all network
    elements in these sections, that are in service. Elements belonging to the same disconnected
    networks section are grouped in lists (e.g. disconnected lines: [[1, 2, 3], [4, 5]]
    means, that lines 1, 2 and 3 are in one disconncted section but are connected to each other.
    The same stands for lines 4, 5.)

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

     OUTPUT:
        **disc_elements** (dict)        - list that contains all network elements, without a
                                          connection to an ext_grid.

                                          format: {'disconnected buses'   : bus_indices,
                                                   'disconnected switches' : switch_indices,
                                                   'disconnected lines'    : line_indices,
                                                   'disconnected trafos'   : trafo_indices
                                                   'disconnected loads'    : load_indices,
                                                   'disconnected gens'     : gen_indices,
                                                   'disconnected sgens'    : sgen_indices}

    """
    import pandapower.topology as top
    mg = top.create_nxgraph(net)
    sections = top.connected_components(mg)
    disc_elements = []

    for section in sections:
        section_dict = {}

        if not section & set(net.ext_grid.bus[net.ext_grid.in_service]).union(
                net.gen.bus[net.gen.slack & net.gen.in_service]) and any(
                net.bus.in_service.loc[section]):
            section_buses = list(net.bus[net.bus.index.isin(section)
                                         & (net.bus.in_service == True)].index)
            section_switches = list(net.switch[net.switch.bus.isin(section_buses)].index)
            section_lines = list(get_connected_elements(net, 'line', section_buses,
                                                        respect_switches=True,
                                                        respect_in_service=True))
            section_trafos = list(get_connected_elements(net, 'trafo', section_buses,
                                                         respect_switches=True,
                                                         respect_in_service=True))

            section_trafos3w = list(get_connected_elements(net, 'trafo3w', section_buses,
                                                           respect_switches=True,
                                                           respect_in_service=True))
            section_gens = list(net.gen[net.gen.bus.isin(section)
                                        & (net.gen.in_service == True)].index)
            section_sgens = list(net.sgen[net.sgen.bus.isin(section)
                                          & (net.sgen.in_service == True)].index)
            section_loads = list(net.load[net.load.bus.isin(section)
                                          & (net.load.in_service == True)].index)

            if section_buses:
                section_dict['buses'] = section_buses
            if section_switches:
                section_dict['switches'] = section_switches
            if section_lines:
                section_dict['lines'] = section_lines
            if section_trafos:
                section_dict['trafos'] = section_trafos
            if section_trafos3w:
                section_dict['trafos3w'] = section_trafos3w
            if section_loads:
                section_dict['loads'] = section_loads
            if section_gens:
                section_dict['gens'] = section_gens
            if section_sgens:
                section_dict['sgens'] = section_sgens

            if any(section_dict.values()):
                disc_elements.append(section_dict)

    open_trafo_switches = net.switch[(net.switch.et == 't') & (net.switch.closed == 0)]
    isolated_trafos = set(
        (open_trafo_switches.groupby("element").count().query("bus > 1").index))
    isolated_trafos_is = isolated_trafos.intersection((set(net.trafo[net.trafo.in_service == True]
                                                           .index)))
    if isolated_trafos_is:
        disc_elements.append({'isolated_trafos': list(isolated_trafos_is)})

    isolated_trafos3w = set(
        (open_trafo_switches.groupby("element").count().query("bus > 2").index))
    isolated_trafos3w_is = isolated_trafos3w.intersection((
        set(net.trafo[net.trafo.in_service == True].index)))
    if isolated_trafos3w_is:
        disc_elements.append({'isolated_trafos3w': list(isolated_trafos3w_is)})

    if disc_elements:
        return disc_elements
Beispiel #6
0
def mv_oberrhein(scenario="load",
                 cosphi_load=0.98,
                 cosphi_pv=1.0,
                 include_substations=False,
                 separation_by_sub=False):
    """
    Loads the Oberrhein network, a generic 20 kV network serviced by two 25 MVA HV/MV transformer
    stations. The network supplies 141 MV/LV substations and 6 MV loads through four MV feeders.
    The network layout is meshed, but the network is operated as a radial network with 6 open
    sectioning points.

    The network can be loaded with two different worst case scenarios for load and generation,
    which are defined by scaling factors for loads / generators as well as tap positions of the
    HV/MV transformers. These worst case scenarios are a good starting point for working with this
    network, but you are of course free to parametrize the network for your use case.

    The network also includes geographical information of lines and buses for plotting.

    OPTIONAL:
        **scenario** - (str, "load"): defines the scaling for load and generation

                - "load": high load scenario, load = 0.6 / sgen = 0, trafo taps [-2, -3]
                - "generation": high feed-in scenario: load = 0.1, generation = 0.8, trafo taps [0, 0]

        **cosphi_load** - (str, 0.98): cosine(phi) of the loads

        **cosphi_sgen** - (str, 1.0): cosine(phi) of the static generators

        **include_substations** - (bool, False): if True, the transformers of the MV/LV level are
        modelled, otherwise the loads representing the LV networks are connected directly to the
        MV node
        
        **separation_by_sub** - (bool, False): if True, the network gets separated into two 
        sections, referring to both substations

    OUTPUT:
         **net** - pandapower network
         
         **net0, net1** - both sections of the pandapower network

    EXAMPLE:

        ``import pandapower.networks``
    
        ``net = pandapower.networks.mv_oberrhein("generation")``
    
        or with separation
    
        ``net0, net1 = pandapower.networks.mv_oberrhein(separation_by_sub=True)``
    """
    if include_substations:
        net = pp.from_json(
            os.path.join(pp_dir, "networks", "mv_oberrhein_substations.json"))
    else:
        net = pp.from_json(
            os.path.join(pp_dir, "networks", "mv_oberrhein.json"))
    net.load.q_mvar = np.tan(np.arccos(cosphi_load)) * net.load.p_mw
    net.sgen.q_mvar = np.tan(np.arccos(cosphi_pv)) * net.sgen.p_mw

    hv_trafos = net.trafo[net.trafo.sn_mva > 1].index
    if scenario == "load":
        net.load.scaling = 0.6
        net.sgen.scaling = 0.0
        net.trafo.tap_pos.loc[hv_trafos] = [-2, -3]
    elif scenario == "generation":
        net.load.scaling = 0.1
        net.sgen.scaling = 0.8
        net.trafo.tap_pos.loc[hv_trafos] = [0, 0]
    else:
        raise ValueError("Unknown scenario %s - chose 'load' or 'generation'" %
                         scenario)

    if separation_by_sub == True:
        # creating multigraph
        mg = top.create_nxgraph(net)
        # clustering connected buses
        zones = [list(area) for area in top.connected_components(mg)]
        net1 = pp.select_subnet(net,
                                buses=zones[0],
                                include_switch_buses=False,
                                include_results=True,
                                keep_everything_else=True)
        net0 = pp.select_subnet(net,
                                buses=zones[1],
                                include_switch_buses=False,
                                include_results=True,
                                keep_everything_else=True)

        pp.runpp(net0)
        pp.runpp(net1)
        return net0, net1

    pp.runpp(net)
    return net
Beispiel #7
0
def vlevel_plotly(net, respect_switches=True, use_line_geodata=None, colors_dict=None, on_map=False,
                  projection=None, map_style='basic', figsize=1, aspectratio='auto', line_width=2,
                  bus_size=10):
    """
    Plots a pandapower network in plotly
    using lines/buses colors according to the voltage level they belong to.
    If no geodata is available, artificial geodata is generated. For advanced plotting see the tutorial

    INPUT:
        **net** - The pandapower format network. If none is provided, mv_oberrhein() will be
        plotted as an example

    OPTIONAL:
        **respect_switches** (bool, True) - Respect switches when artificial geodata is created

        **use_line_geodata** (bool, True) - defines if lines patches are based on net.line_geodata of the lines (True)
        or on net.bus_geodata of the connected buses (False)

        *colors_dict** (dict, None) - dictionary for customization of colors for each voltage level in the form:
        voltage_kv : color

        **on_map** (bool, False) - enables using mapbox plot in plotly If provided geodata are not real
        geo-coordinates in lon/lat form, on_map will be set to False.

        **projection** (String, None) - defines a projection from which network geo-data will be transformed to
        lat-long. For each projection a string can be found at http://spatialreference.org/ref/epsg/

        **map_style** (str, 'basic') - enables using mapbox plot in plotly

            - 'streets'
            - 'bright'
            - 'light'
            - 'dark'
            - 'satellite'

        **figsize** (float, 1) - aspectratio is multiplied by it in order to get final image size

        **aspectratio** (tuple, 'auto') - when 'auto' it preserves original aspect ratio of the network geodata
        any custom aspectration can be given as a tuple, e.g. (1.2, 1)

        **line_width** (float, 1.0) - width of lines

        **bus_size** (float, 10.0) -  size of buses to plot.

    """
    version_check()
    # create geocoord if none are available
    if 'line_geodata' not in net:
        net.line_geodata = pd.DataFrame(columns=['coords'])
    if 'bus_geodata' not in net:
        net.bus_geodata = pd.DataFrame(columns=["x", "y"])
    if len(net.line_geodata) == 0 and len(net.bus_geodata) == 0:
        logger.warning("No or insufficient geodata available --> Creating artificial coordinates." +
                       " This may take some time")
        create_generic_coordinates(net, respect_switches=respect_switches)
        if on_map:
            logger.warning("Map plots not available with artificial coordinates and will be disabled!")
            on_map = False

    # check if geodata are real geographycal lat/lon coordinates using geopy
    if on_map and projection is not None:
        geo_data_to_latlong(net, projection=projection)

    # if bus geodata is available, but no line geodata
    if use_line_geodata is None:
        use_line_geodata = False if len(net.line_geodata) == 0 else True
    elif use_line_geodata and len(net.line_geodata) == 0:
        logger.warning("No or insufficient line geodata available --> only bus geodata will be used.")
        use_line_geodata = False

    # getting connected componenets without consideration of trafos
    graph = create_nxgraph(net, include_trafos=False)
    vlev_buses = connected_components(graph)
    # getting unique sets of buses for each voltage level
    vlev_bus_dict = {}
    for vl_buses in vlev_buses:
        if net.bus.loc[vl_buses, 'vn_kv'].unique().shape[0] > 1:
            logger.warning('buses from the same voltage level does not have the same vn_kv !?')
        vn_kv = net.bus.loc[vl_buses, 'vn_kv'].unique()[0]
        if vlev_bus_dict.get(vn_kv):
            vlev_bus_dict[vn_kv].update(vl_buses)
        else:
            vlev_bus_dict[vn_kv] = vl_buses

    # create a default colormap for voltage levels
    nvlevs = len(vlev_bus_dict)
    colors = get_plotly_color_palette(nvlevs)
    colors_dict = dict(zip(vlev_bus_dict.keys(), colors))

    # creating traces for buses and lines for each voltage level
    bus_traces = []
    line_traces = []
    for vn_kv, buses_vl in vlev_bus_dict.items():

        vlev_color = colors_dict[vn_kv]
        bus_trace_vlev = create_bus_trace(net, buses=buses_vl, size=bus_size, legendgroup=str(vn_kv),
                                          color=vlev_color, trace_name='buses {0} kV'.format(vn_kv))
        if bus_trace_vlev is not None:
            bus_traces += bus_trace_vlev

        vlev_lines = net.line[net.line.from_bus.isin(buses_vl) & net.line.to_bus.isin(buses_vl)].index.tolist()
        line_trace_vlev = create_line_trace(net, lines=vlev_lines, use_line_geodata=use_line_geodata,
                                            respect_switches=respect_switches, legendgroup=str(vn_kv),
                                            color=vlev_color, width=line_width, trace_name='lines {0} kV'.format(vn_kv))
        if line_trace_vlev is not None:
            line_traces += line_trace_vlev

    trafo_traces = create_trafo_trace(net, color='gray', width=line_width * 2)

    draw_traces(line_traces + trafo_traces + bus_traces, showlegend=True,
                aspectratio=aspectratio, on_map=on_map, map_style=map_style, figsize=figsize)
Beispiel #8
0
    draw_traces(line_traces + trafo_traces + bus_traces, showlegend=True,
                aspectratio=aspectratio, on_map=on_map, map_style=map_style, figsize=figsize)
    
if __name__ == '__main__':
    from pandapower.plotting.plotly import simple_plotly
    from pandapower.networks import mv_oberrhein
    from pandapower import runpp
    net = mv_oberrhein()
    vlevel_plotly(net)
    runpp(net)
    line_width=2
    bus_size=10
    use_line_geodata = None
    graph = create_nxgraph(net, include_trafos=False)
    vlev_buses = connected_components(graph)
    respect_switches = True
    
    # getting unique sets of buses for each voltage level
    vlev_bus_dict = {}
    for vl_buses in vlev_buses:
        if net.bus.loc[vl_buses, 'vn_kv'].unique().shape[0] > 1:
            logger.warning('buses from the same voltage level does not have the same vn_kv !?')
        vn_kv = net.bus.loc[vl_buses, 'vn_kv'].unique()[0]
        if vlev_bus_dict.get(vn_kv):
            vlev_bus_dict[vn_kv].update(vl_buses)
        else:
            vlev_bus_dict[vn_kv] = vl_buses
            
    # create a default colormap for voltage levels
    nvlevs = len(vlev_bus_dict)
Beispiel #9
0
def vlevel_plotly(net, respect_switches=True, use_line_geodata=None, colors_dict=None, on_map=False,
                  projection=None, map_style='basic', figsize=1, aspectratio='auto', line_width=2,
                  bus_size=10, filename="temp-plot.html", auto_open=True):
    """
    Plots a pandapower network in plotly
    using lines/buses colors according to the voltage level they belong to.
    If no geodata is available, artificial geodata is generated. For advanced plotting see the
    tutorial

    INPUT:
        **net** - The pandapower format network. If none is provided, mv_oberrhein() will be
        plotted as an example

    OPTIONAL:
        **respect_switches** (bool, True) - Respect switches when artificial geodata is created

        **use_line_geodata** (bool, True) - defines if lines patches are based on net.line_geodata
            of the lines (True) or on net.bus_geodata of the connected buses (False)

        *colors_dict** (dict, None) - dictionary for customization of colors for each voltage level
            in the form: voltage : color

        **on_map** (bool, False) - enables using mapbox plot in plotly If provided geodata are not
            real geo-coordinates in lon/lat form, on_map will be set to False.

        **projection** (String, None) - defines a projection from which network geo-data will be
            transformed to lat-long. For each projection a string can be found at
            http://spatialreference.org/ref/epsg/

        **map_style** (str, 'basic') - enables using mapbox plot in plotly

            - 'streets'
            - 'bright'
            - 'light'
            - 'dark'
            - 'satellite'

        **figsize** (float, 1) - aspectratio is multiplied by it in order to get final image size

        **aspectratio** (tuple, 'auto') - when 'auto' it preserves original aspect ratio of the
            network geodata any custom aspectration can be given as a tuple, e.g. (1.2, 1)

        **line_width** (float, 1.0) - width of lines

        **bus_size** (float, 10.0) -  size of buses to plot.

        **filename** (str, "temp-plot.html") - filename / path to plot to. Should end on `*.html`

        **auto_open** (bool, True) - automatically open plot in browser

    OUTPUT:
        **figure** (graph_objs._figure.Figure) figure object

    """
    # getting connected componenets without consideration of trafos
    graph = create_nxgraph(net, include_trafos=False)
    vlev_buses = connected_components(graph)
    # getting unique sets of buses for each voltage level
    vlev_bus_dict = {}
    for vl_buses in vlev_buses:
        if net.bus.loc[vl_buses, 'vn_kv'].unique().shape[0] > 1:
            logger.warning('buses from the same voltage level does not have the same vn_kv !?')
        vn_kv = net.bus.loc[vl_buses, 'vn_kv'].unique()[0]
        if vlev_bus_dict.get(vn_kv):
            vlev_bus_dict[vn_kv].update(vl_buses)
        else:
            vlev_bus_dict[vn_kv] = vl_buses

    # create a default colormap for voltage levels
    nvlevs = len(vlev_bus_dict)
    colors = get_plotly_color_palette(nvlevs)
    colors_dict = colors_dict or dict(zip(vlev_bus_dict.keys(), colors))
    bus_groups = [(buses, colors_dict[vlev], f"{vlev} kV") for vlev, buses in vlev_bus_dict.items()]

    return _draw_colored_bus_groups_plotly(
        net, bus_groups, respect_switches=respect_switches,
        use_line_geodata=use_line_geodata, on_map=on_map, projection=projection,
        map_style=map_style, figsize=figsize, aspectratio=aspectratio, line_width=line_width,
        bus_size=bus_size, filename=filename, auto_open=auto_open)
# Youtube Tutorial: https://www.youtube.com/watch?v=QYDp_-TX7C4
import pandapower as pp
import pandapower.plotting as pplt
import pandapower.topology as top
import pandapower.networks as nw
import matplotlib.pyplot as plt
import seaborn as sns

net = nw.mv_oberrhein()
pplt.simple_plot(net)

mg = top.create_nxgraph(net, nogobuses=set(net.trafo.lv_bus.values) | set(net.trafo.hv_bus.values))
colors = sns.color_palette()
collections = list()
sizes = pplt.get_collection_sizes(net)
for area, color in zip(top.connected_components(mg), colors):
    collections.append(pplt.create_bus_collection(net, area, color=color, size=sizes["bus"]))
    line_ind = net.line.loc[:, "from_bus"].isin(area) | net.line.loc[:, "to_bus"].isin(area)
    lines = net.line.loc[line_ind].index
    collections.append(pplt.create_line_collection(net, lines, color=color))
collections.append(pplt.create_ext_grid_collection(net, size=sizes["ext_grid"]))
pplt.draw_collections(collections)
plt.show()