Skip to content

Commit

Permalink
Merge branch 'e2nIEE:develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
mrifraunhofer committed Jul 30, 2024
2 parents 8c417ac + ed0e8e5 commit a08ad7c
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Change Log
- [FIXED] error during unbalanced powerflow due to out of service external grids
- [FIXED] PowerFactory converter: fix trafo3w tap dependent impedance
- [ADDED] PowerFactory converter: support load types (constI, constZ) and the setting whether to consider voltage dependency of loads
- [CHANGED] vectorization of y_bus reordering in _calculate_equivalent_Ybus() within get_equivalent()
- [FIXED] deprecation of matplotlib.cm.get_cmap(name) -> matplotlib.colormaps[name]
- [FIXED] merge_nets failing if net2 has custom DataFrame that is not present in net1
- [FIXED] fixed some small bugs in the CGMES converter and improved its speed
Expand Down
2 changes: 1 addition & 1 deletion pandapower/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -2416,7 +2416,7 @@ def create_line_from_parameters(net, from_bus, to_bus, length_km, r_ohm_per_km,
"them for all parameters, otherwise they are not set!")

if geodata is not None:
net.line.at[index, "geo"] = f'{{"type":"LineString", "coordinates":{geodata}}}'
net.line.at[index, "geo"] = f'{{"coordinates":{geodata}, "type":"LineString"}}'
else:
net.line.at[index, "geo"] = None

Expand Down
39 changes: 24 additions & 15 deletions pandapower/plotting/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@ class TextPath: # so that the test does not fail
logger = logging.getLogger(__name__)


def _get_coords_from_geojson(gj_str):
pattern = r'"coordinates"\s*:\s*((?:\[(?:\[[^]]+],?\s*)+\])|\[[^]]+\])'
matches = re.findall(pattern, gj_str)

if not matches:
return None
if len(matches) > 1:
raise ValueError("More than one match found in GeoJSON string")
for m in matches:
return ast.literal_eval(m)
return None


class CustomTextPath(TextPath):
"""
Create a path from the text. This class provides functionality for deepcopy, which is not
Expand Down Expand Up @@ -422,7 +435,16 @@ def create_bus_collection(net, buses=None, size=5, patch_type="circle", color=No
if any(net.bus.geo.isna()):
raise AttributeError('net.bus.geo contains NaN values, consider dropping them beforehand.')

coords = net.bus.geo.apply(geojson.loads).apply(geojson.utils.coords).apply(next).loc[buses].to_list()
if bus_geodata is None:
bus_geodata = net.bus.geo.apply(_get_coords_from_geojson)

buses_with_geo = buses[np.isin(buses, bus_geodata.index.values)]
if len(buses_with_geo) < len(buses):
logger.warning(
f"The following buses cannot be displayed as there is on geodata available: {set(buses)-set(buses_with_geo)}"
)

coords = bus_geodata.loc[buses_with_geo].values

infos = [infofunc(bus) for bus in buses] if infofunc is not None else []

Expand Down Expand Up @@ -486,20 +508,7 @@ def create_line_collection(net: pandapowerNet, lines=None,
if not MATPLOTLIB_INSTALLED:
soft_dependency_error(str(sys._getframe().f_code.co_name)+"()", "matplotlib")

def _get_coords_from_geojson(gj_str):
pattern = r'"coordinates"\s*:\s*((?:\[(?:\[[^]]+],?\s*)+\])|\[[^]]+\])'
matches = re.findall(pattern, gj_str)

if not matches:
return None
if len(matches) > 1:
raise ValueError("More than one match found in GeoJSON string")
for m in matches:
return ast.literal_eval(m)
return None

if use_bus_geodata is False and line_geodata is None and (
"geo" not in net.line.columns or net.line.geo.isnull().all()):
if use_bus_geodata is False and line_geodata is None and ("geo" not in net.line.columns or net.line.geo.empty):
# if bus geodata is available, but no line geodata
logger.warning("use_bus_geodata is automatically set to True, since net.line.geo is empty.")
use_bus_geodata = True
Expand Down
9 changes: 7 additions & 2 deletions pandapower/plotting/geo.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,11 @@ def _get_props(r, c, p) -> None:
except (ValueError, TypeError):
p[col] = str(r[col])

def update_props(r: pd.Series) -> None:
if r.name not in props:
props[r.name] = {}
props[r.name].update(r.to_dict())

missing_geom: List[int] = [0, 0, 0, 0] # missing nodes, branches, switches, trafos
features = []
# build geojson features for nodes
Expand All @@ -365,7 +370,7 @@ def _get_props(r, c, p) -> None:
tempdf.index = tempdf.apply(lambda r: f"{r['pp_type']}-{r['pp_index']}", axis=1)
tempdf.drop(columns=['geo'], inplace=True, axis=1, errors='ignore')

props.update(tempdf.to_dict(orient='index'))
tempdf.apply(update_props, axis=1)
if isinstance(nodes, bool):
iterator = node_geodata.items()
else:
Expand All @@ -390,7 +395,7 @@ def _get_props(r, c, p) -> None:
tempdf.index = tempdf.apply(lambda r: f"{r['pp_type']}-{r['pp_index']}", axis=1)
tempdf.drop(columns=['geo'], inplace=True, axis=1, errors='ignore')

props.update(tempdf.to_dict(orient='index'))
tempdf.apply(update_props, axis=1)

# Iterating over pipe_geodata won't work
# pipe_geodata only contains pipes that have inflection points!
Expand Down
13 changes: 13 additions & 0 deletions pandapower/test/plotting/test_geo.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,19 @@ def test_dump_to_geojson():
assert isinstance(result, FeatureCollection)
assert dumps(result, sort_keys=True) == '{"features": [{"geometry": {"coordinates": [[1.0, 2.0], [3.0, 4.0]], "type": "LineString"}, "id": "line-0", "properties": {"c_nf_per_km": 720.0, "df": 1.0, "from_bus": 1, "g_us_per_km": 0.0, "ices": 0.389985, "in_service": true, "length_km": 1.0, "max_i_ka": 0.328, "name": "line1", "parallel": 1, "pp_index": 0, "pp_type": "line", "r_ohm_per_km": 0.2067, "std_type": null, "to_bus": 7, "type": null, "x_ohm_per_km": 0.1897522}, "type": "Feature"}], "type": "FeatureCollection"}'

# test exporting props from bus and res_bus
_net.res_bus.loc[1, ["vm_pu", "va_degree", "p_mw", "q_mvar"]] = [1.0, 1.0, 1.0, 1.0]
result = geo.dump_to_geojson(_net, nodes=[1])
assert isinstance(result, FeatureCollection)
assert dumps(result, sort_keys=True) == '{"features": [{"geometry": {"coordinates": [1.0, 2.0], "type": "Point"}, "id": "bus-1", "properties": {"in_service": true, "name": "bus2", "p_mw": 1.0, "pp_index": 1, "pp_type": "bus", "q_mvar": 1.0, "type": "b", "va_degree": 1.0, "vm_pu": 1.0, "vn_kv": 0.4, "zone": null}, "type": "Feature"}], "type": "FeatureCollection"}'

# test exporting props from bus and res_bus
_net.res_line.loc[0, _net.res_line.columns] = [7.0]*len(_net.res_line.columns)
result = geo.dump_to_geojson(_net, branches=[0])
assert isinstance(result, FeatureCollection)
assert dumps(result, sort_keys=True) == '{"features": [{"geometry": {"coordinates": [[1.0, 2.0], [3.0, 4.0]], "type": "LineString"}, "id": "line-0", "properties": {"c_nf_per_km": 720.0, "df": 1.0, "from_bus": 1, "g_us_per_km": 0.0, "i_from_ka": 7.0, "i_ka": 7.0, "i_to_ka": 7.0, "ices": 0.389985, "in_service": true, "length_km": 1.0, "loading_percent": 7.0, "max_i_ka": 0.328, "name": "line1", "p_from_mw": 7.0, "p_to_mw": 7.0, "parallel": 1, "pl_mw": 7.0, "pp_index": 0, "pp_type": "line", "q_from_mvar": 7.0, "q_to_mvar": 7.0, "ql_mvar": 7.0, "r_ohm_per_km": 0.2067, "std_type": null, "to_bus": 7, "type": null, "va_from_degree": 7.0, "va_to_degree": 7.0, "vm_from_pu": 7.0, "vm_to_pu": 7.0, "x_ohm_per_km": 0.1897522}, "type": "Feature"}], "type": "FeatureCollection"}'



def test_convert_geodata_to_geojson():
pytest.importorskip("geojson")
Expand Down

0 comments on commit a08ad7c

Please sign in to comment.