Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ADDED] toolbox functions #2176

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Change Log
- [ADDED] option to use a second tap changer for the trafo element
- [CHANGED] parameters of function merge_internal_net_and_equivalent_external_net()
- [FIXED] :code:`convert_format.py`: update the attributes of the characteristic objects to match the new characteristic
- [ADDED] toolbox functions branch_buses_df(), branches_parallel_to_bus_bus_switches(), check_parallel_branch_to_bus_bus_switch()
- [FIXED] additional arguments from mpc saved to net._options: create "_options" if it does not exist
- [CHANGED] cim2pp: extracted getting default classes, added generic setting datatypes from CGMES XMI schema

Expand Down
6 changes: 6 additions & 0 deletions doc/toolbox.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ Item/Element Selection

.. autofunction:: pandapower.toolbox.count_elements

.. autofunction:: pandapower.toolbox.branch_buses_df

.. autofunction:: pandapower.toolbox.branches_parallel_to_bus_bus_switches

.. autofunction:: pandapower.toolbox.check_parallel_branch_to_bus_bus_switch

.. autofunction:: pandapower.toolbox.get_gc_objects_dict

====================================
Expand Down
55 changes: 55 additions & 0 deletions pandapower/test/toolbox/test_element_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# Copyright (c) 2016-2023 by University of Kassel and Fraunhofer Institute for Energy Economics
# and Energy System Technology (IEE), Kassel. All rights reserved.
import numpy as np
import pandas as pd
import pytest

Expand Down Expand Up @@ -219,5 +220,59 @@ def test_count_elements():
assert set(received.index) == pandapower.toolbox.pp_elements()


def test_branch_buses_df():
net = nw.example_multivoltage()
df = pp.branch_buses_df(net, "line")
assert np.allclose(df.iloc[:, :2], net.line[["from_bus", "to_bus"]].values)
assert set(df.element_type) == {"line"}
assert list(df.columns) == ["bus1", "bus2", "element_type", "element_index"]

df = pp.branch_buses_df(net, "trafo3w", ["hv_bus", "mv_bus", "lv_bus"])
assert list(df.columns) == ["bus1", "bus2", "element_type", "element_index"]
assert len(df) == 3*len(net.trafo3w)


def test_branches_parallel_to_bus_bus_switches():
net = nw.example_multivoltage()

assert pp.branches_parallel_to_bus_bus_switches(net).shape == (0, 4)

sw_p = pp.create_switch(net, net.trafo.lv_bus.at[0], net.trafo.hv_bus.at[0], "b", closed=False)
assert pp.branches_parallel_to_bus_bus_switches(net).shape == (2, 4)
assert pp.branches_parallel_to_bus_bus_switches(net, keep="first").shape == (1, 4)
assert pp.branches_parallel_to_bus_bus_switches(net, keep="last").shape == (1, 4)
assert pp.branches_parallel_to_bus_bus_switches(net, closed_switches_only=True).shape == (0, 4)
assert pp.branches_parallel_to_bus_bus_switches(
net, switches=net.switch.index.difference([sw_p])).shape == (0, 4)

# switch bus order of bus-bus switch
net.switch.loc[sw_p, ["bus", "element"]] = net.switch.loc[sw_p, ["element", "bus"]].values

assert pp.branches_parallel_to_bus_bus_switches(
net, branch_types=["line", "trafo3w"]).shape == (0, 4)
assert pp.branches_parallel_to_bus_bus_switches(
net, branch_types=["trafo", "trafo3w"]).shape == (2, 4)


def test_check_parallel_branch_to_bus_bus_switch():
net = nw.example_multivoltage()

assert not pp.check_parallel_branch_to_bus_bus_switch(net)

sw_p = pp.create_switch(net, net.trafo.lv_bus.at[0], net.trafo.hv_bus.at[0], "b", closed=False)
assert pp.check_parallel_branch_to_bus_bus_switch(net)
assert not pp.check_parallel_branch_to_bus_bus_switch(net, closed_switches_only=True)
assert not pp.check_parallel_branch_to_bus_bus_switch(
net, switches=net.switch.index.difference([sw_p]))

# switch bus order of bus-bus switch
net.switch.loc[sw_p, ["bus", "element"]] = net.switch.loc[sw_p, ["element", "bus"]].values

assert not pp.check_parallel_branch_to_bus_bus_switch(
net, branch_types=["line", "trafo3w"])
assert pp.check_parallel_branch_to_bus_bus_switch(
net, branch_types=["trafo", "trafo3w"])


if __name__ == '__main__':
pytest.main([__file__, "-x"])
162 changes: 160 additions & 2 deletions pandapower/toolbox/element_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@
connected_elements = set(element_table.index[(element_table.bus.isin(buses))])
elif element_type in ['_equiv_trafo3w']:
# ignore '_equiv_trafo3w'
return {}
return set()

Check warning on line 206 in pandapower/toolbox/element_selection.py

View check run for this annotation

Codecov / codecov/patch

pandapower/toolbox/element_selection.py#L206

Added line #L206 was not covered by tests
else:
raise UserWarning(f"Unknown element type {element_type}!")

Expand Down Expand Up @@ -707,4 +707,162 @@
dtype: int32
"""
return pd.Series({et: net[et].shape[0] for et in pp_elements(**kwargs) if return_empties or \
bool(net[et].shape[0])}, dtype=np.int64)
bool(net[et].shape[0])}, dtype=np.int64)


def branch_buses_df(net, branch_type, bus_columns=None):
"""Returns a DataFrame which summarizes the buses to which the elements of defined element_type
are connected to.

Parameters
----------
net : pp.pandapowerNet
pandapower net
branch_type : str
branch type, e.g. "trafo", "trafo3w" or "line"
bus_columns : list[str]
list of bus columns of the element type table; if None, all columns from are used

Returns
-------
pd.DataFrame
summary of the buses to which the elements of defined element_type are connected to.

Example
-------
>>> import pandapower as pp
>>> net = pp.networks.example_multivoltage()
>>> pp.branch_buses_df(net, "trafo3w")
bus1 bus2 element_type element_index
0 33 36 trafo3w 0
1 33 37 trafo3w 0
2 36 37 trafo3w 0
"""
if bus_columns is None:
bus_columns = branch_element_bus_dict()[branch_type]
if len(bus_columns) == 2:
return net[branch_type][bus_columns].set_axis(["bus1", "bus2"], axis="columns").assign(
element_type=branch_type, element_index=net[branch_type].index)
elif len(bus_columns) == 3:
bus_combis = [[bus_columns[0], bus_columns[1]],
[bus_columns[0], bus_columns[2]],
[bus_columns[1], bus_columns[2]]]
return pd.concat([net[branch_type][bus_combi].set_axis(
["bus1", "bus2"], axis="columns").assign(element_type=branch_type, element_index=net[
branch_type].index) for bus_combi in bus_combis], ignore_index=True)
else:
raise NotImplementedError(f"{len(bus_columns)=} is not implemented.")

Check warning on line 754 in pandapower/toolbox/element_selection.py

View check run for this annotation

Codecov / codecov/patch

pandapower/toolbox/element_selection.py#L754

Added line #L754 was not covered by tests


def branches_parallel_to_bus_bus_switches(
net, branch_types=None, switches=None, closed_switches_only=False, keep=False):
"""Returns a DataFrame of branches and/or bus-bus switches that are in parallel

Parameters
----------
net : pp.pandapowerNet
pandapower net
branch_types : list[str], optional
list of names of branch types to be considered, by default None
switches : iterable, optional
list of switches to be considered, by default None
closed_switches_only : bool, optional
if True, the list of considered switches is reduced to only closed switches, by default False
keep : bool, optional
decides whether the returned DataFrame contains the branches ("last"),
the switches ("first") or both (False), by default False

Returns
-------
pd.DataFrame
branches and/or bus-bus switches that are in parallel

Note
----
The returned branches do not necessarily contain all branches that are parallel to bus-bus
switches.

Example
-------
>>> import pandapower as pp
>>> net = pp.networks.example_multivoltage()
>>> pp.create_switch(net, net.trafo.lv_bus.at[0], net.trafo.hv_bus.at[0], "b", closed=False)
88
>>> pp.branches_parallel_to_bus_bus_switches(net)
bus1 bus2 element_type element_index
26 13 17 trafo 0
65 13 17 switch 88
>>> pp.branches_parallel_to_bus_bus_switches(net, closed_switches_only=True)
Empty DataFrame
Columns: [bus1, bus2, element_type, element_index]
Index: []
"""

considered_sw_df = net.switch if switches is None else net.switch.loc[switches]
if closed_switches_only:
considered_sw_df = considered_sw_df.loc[considered_sw_df.closed]
bb_sw = considered_sw_df.loc[considered_sw_df.et == "b", ["bus", "element"]].set_axis(
["bus1", "bus2"], axis="columns")
bb_sw = bb_sw.assign(element_type="switch", element_index=bb_sw.index)
if not len(bb_sw):
return pd.DataFrame({

Check warning on line 808 in pandapower/toolbox/element_selection.py

View check run for this annotation

Codecov / codecov/patch

pandapower/toolbox/element_selection.py#L808

Added line #L808 was not covered by tests
'bus1': int(), 'bus2': int(), 'element_type': str(), 'element_index': int()}, index=[])
bebd = branch_element_bus_dict()
if branch_types is not None:
bebd = {key: val for key, val in bebd.items() if key in branch_types}
bra_buses = pd.concat([branch_buses_df(net, et, bus_columns) \
for et, bus_columns in bebd.items()], ignore_index=True)

# drop duplicates
bb_sw.drop_duplicates(subset=["bus1", "bus2"], inplace=True)
bra_buses.drop_duplicates(subset=["bus1", "bus2"], inplace=True)

# order bbs_sw and bra_buses
to_order = bb_sw.bus1 > bb_sw.bus2
bb_sw.loc[to_order, ["bus1", "bus2"]] = bb_sw.loc[to_order, ["bus2", "bus1"]].values
to_order = bra_buses.bus1 > bra_buses.bus2
bra_buses.loc[to_order, ["bus1", "bus2"]] = bra_buses.loc[to_order, ["bus2", "bus1"]].values

# merge bb_sw and bra_buses
df = pd.concat([bra_buses, bb_sw], ignore_index=True)
df = df.loc[df.duplicated(subset=["bus1", "bus2"], keep=keep)]
return df # further parallel branches in parallel to the returned branches can exist


def check_parallel_branch_to_bus_bus_switch(
net, branch_types=None, switches=None, closed_switches_only=False):
"""Returns a DataFrame of branches and/or bus-bus switches that are in parallel

Parameters
----------
net : pp.pandapowerNet
pandapower net
branch_types : list[str], optional
list of names of branch types to be considered, by default None
switches : iterable, optional
list of switches to be considered, by default None
closed_switches_only : bool, optional
if True, the list of considered switches is reduced to only closed switches, by default False

Returns
-------
bool
whether aa least one branch (of given branch types) is parallel to a bus-bus
switches (of the given (closed) switches)

Example
-------
>>> import pandapower as pp
>>> net = pp.networks.example_multivoltage()
>>> pp.create_switch(net, net.trafo.lv_bus.at[0], net.trafo.hv_bus.at[0], "b", closed=False)
88
>>> pp.check_parallel_branch_to_bus_bus_switch(net)
True
>>> pp.check_parallel_branch_to_bus_bus_switch(net, closed_switches_only=True)
False
"""
return bool(len(
branches_parallel_to_bus_bus_switches(
net, branch_types=branch_types, switches=switches,
closed_switches_only=closed_switches_only)
))
Loading