Skip to content
Merged
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
2 changes: 1 addition & 1 deletion pandapower/auxiliary.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import numbers
import warnings
from collections.abc import MutableMapping, Iterable, Collection
from collections.abc import Iterable, Collection
from importlib.metadata import PackageNotFoundError
from importlib.metadata import version as version_str
from typing import (
Expand Down
58 changes: 32 additions & 26 deletions pandapower/convert_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
logger = logging.getLogger(__name__)


def convert_format(net, elements_to_deserialize=None, drop_invalid_geodata=False):

Check failure on line 24 in pandapower/convert_format.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 24 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=e2nIEE_pandapower&issues=AZ5PqyfBbFGUaxzRzhxm&open=AZ5PqyfBbFGUaxzRzhxm&pullRequest=2813
"""
Converts old nets to new format to ensure consistency. The converted net is returned.
"""
Expand All @@ -44,6 +44,12 @@
if not bool(cols.issubset(net.load.columns)):
for col in cols:
add_column_to_df(net, "load", col)

# drop empty res_ tables and _empty_res_ tables
for key in list(net.keys()): # conversion to list required because of dict modification while iteration

Check warning on line 49 in pandapower/convert_format.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unnecessary `list()` call on an already iterable object.

See more on https://sonarcloud.io/project/issues?id=e2nIEE_pandapower&issues=AZ5PqyfBbFGUaxzRzhxn&open=AZ5PqyfBbFGUaxzRzhxn&pullRequest=2813
if key.startswith("_empty_res_") or (key.startswith("res_") and len(net[key]) == 0):
del net[key]

if net_format_version < Version("3.1.0"):
_convert_q_capability_characteristic(net)
if Version("3.0.0") <= net_format_version < Version("3.1.3"):
Expand Down Expand Up @@ -155,12 +161,12 @@
"""Restores dataframes index names stored as dictionary. With newer pp to_json() this
information is stored to the dataframe its self.
"""
if "index_names" in net.keys():
if "index_names" in net:
if not isinstance(net["index_names"], dict):
raise ValueError("To restore the index names of the dataframes, a dict including this "
f"information is expected, not {type(net['index_names'])}")
for key, index_name in net["index_names"].items():
if key in net.keys():
if key in net:
net[key].index.name = index_name
del net["index_names"]

Expand Down Expand Up @@ -208,19 +214,19 @@
controller = net.controller.at[ctrl_idx, "object"]
if issubclass(type(controller), TrafoController):

if "tid" in controller.__dict__.keys():
if "tid" in controller.__dict__:
controller.__dict__["element_index"] = controller.__dict__.pop("tid")
elif "transformer_index" in controller.__dict__.keys():
elif "transformer_index" in controller.__dict__:
controller.__dict__["element_index"] = controller.__dict__.pop("transformer_index")

if "trafotable" in controller.__dict__.keys():
if "trafotable" in controller.__dict__:
controller.__dict__["element"] = controller.__dict__.pop("trafotable")
if "trafotype" in controller.__dict__.keys():
if "trafotype" in controller.__dict__:
del controller.__dict__["trafotype"]
elif "trafotype" in controller.__dict__.keys():
elif "trafotype" in controller.__dict__:
controller.__dict__["element"] = controller.__dict__.pop("trafotype")

if "controlled_bus" in controller.__dict__.keys():
if "controlled_bus" in controller.__dict__:
controller.__dict__["trafobus"] = controller.__dict__.pop("controlled_bus")


Expand Down Expand Up @@ -289,8 +295,8 @@
def _add_missing_tables(net):
net_new = pandapowerNet(name='missing_tables_net')
net_new.name = "" # name is set to avoid warnings, then unset here to avoid adding it to any network
for key in net_new.keys():
if key.startswith("_empty_res") or key not in net.keys():
for key in net_new:
if key.startswith("_empty_res") or key not in net:
net[key] = net_new[key]


Expand Down Expand Up @@ -374,7 +380,7 @@
if "controller" in net:
net["controller"] = net["controller"].rename(columns={"controller": "object"})

if _check_elements_to_deserialize('res_line_3ph', elements_to_deserialize):
if 'res_line_3ph' in net and _check_elements_to_deserialize('res_line_3ph', elements_to_deserialize):
if "p_a_l_mw" in net.res_line_3ph:
net['res_line_3ph'] = net['res_line_3ph'].rename(columns={
'p_a_l_mw': 'pl_a_mw',
Expand All @@ -385,7 +391,7 @@
'q_c_l_mvar': 'ql_c_mvar',
})

if _check_elements_to_deserialize('res_trafo_3ph', elements_to_deserialize):
if 'res_trafo_3ph' in net and _check_elements_to_deserialize('res_trafo_3ph', elements_to_deserialize):
if "p_a_l_mw" in net.res_trafo_3ph:
net['res_trafo_3ph'] = net['res_trafo_3ph'].rename(columns={
'p_a_l_mw': 'pl_a_mw',
Expand Down Expand Up @@ -517,16 +523,16 @@
net.switch['in_ka'] = np.nan

# Update the switch table with 'in_ka'
if _check_elements_to_deserialize('res_switch', elements_to_deserialize) and \
'p_from_mw' not in net.res_switch:
net.res_switch['p_from_mw'] = np.nan
net.res_switch['q_from_mvar'] = np.nan
net.res_switch['p_to_mw'] = np.nan
net.res_switch['q_to_mvar'] = np.nan
if ('res_switch' in net and _check_elements_to_deserialize('res_switch', elements_to_deserialize) and
'p_from_mw' not in net.res_switch):
net.res_switch['p_from_mw'] = np.nan
net.res_switch['q_from_mvar'] = np.nan
net.res_switch['p_to_mw'] = np.nan
net.res_switch['q_to_mvar'] = np.nan

# Update the switch table with 'in_ka'
if _check_elements_to_deserialize('res_switch_est', elements_to_deserialize) and \
'p_from_mw' not in net.res_switch_est:
if ('res_switch_est' in net and _check_elements_to_deserialize('res_switch_est', elements_to_deserialize) and
'p_from_mw' not in net.res_switch_est):
net.res_switch_est['p_from_mw'] = np.nan
net.res_switch_est['q_from_mvar'] = np.nan
net.res_switch_est['p_to_mw'] = np.nan
Expand Down Expand Up @@ -560,8 +566,8 @@
"slack_weight" not in net.xward:
net.xward['slack_weight'] = 0.0

if _check_elements_to_deserialize('res_line_3ph', elements_to_deserialize) and \
"p_c_from_mw" not in net.res_line_3ph:
if ('res_line_3ph' in net and _check_elements_to_deserialize('res_line_3ph', elements_to_deserialize) and
"p_c_from_mw" not in net.res_line_3ph):
net.res_line_3ph['p_c_from_mw'] = np.nan
net.res_line_3ph['loading_a_percent'] = np.nan
net.res_line_3ph['loading_b_percent'] = np.nan
Expand All @@ -570,8 +576,8 @@

def _update_trafo_type_parameter_names(net):
for element in ('trafo', 'trafo3w'):
for type in net.std_types[element].keys():
keys = {col: _update_column(col) for col in net.std_types[element][type].keys() if
for type in net.std_types[element]:
keys = {col: _update_column(col) for col in net.std_types[element][type] if
col.startswith("tp") or col.startswith("vsc")}
for old_key, new_key in keys.items():
net.std_types[element][type][new_key] = net.std_types[element][type].pop(old_key)
Expand Down Expand Up @@ -614,7 +620,7 @@

def _convert_to_mw(net):
replace = [("kw", "mw"), ("kvar", "mvar"), ("kva", "mva")]
for element in net.keys():
for element in net:
if isinstance(net[element], pd.DataFrame):
for old, new in replace:
diff = {column: column.replace(old, new) for column in net[element].columns if
Expand Down Expand Up @@ -682,7 +688,7 @@
"""
_check_elements_to_deserialize('controller', elements_to_deserialize)
if _check_elements_to_deserialize('controller', elements_to_deserialize) and \
"controller" in net.keys():
"controller" in net:
for obj in net["controller"].object.values:
_update_object_attributes(obj)

Expand Down
1 change: 0 additions & 1 deletion pandapower/converter/cim/cim2pp/build_pp_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@


class CimConverter:

def __init__(self, cim_parser: cim_classes.CimParser, converter_classes: Dict,
cim_version: str | None = None, **kwargs):
self.logger = logging.getLogger(self.__class__.__name__)
Expand Down
29 changes: 17 additions & 12 deletions pandapower/converter/cim/cim_tools.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2016-2026 by University of Kassel and Fraunhofer Institute for Energy Economics
# and Energy System Technology (IEE), Kassel. All rights reserved.

import logging
import os
import json
from typing import Dict, List

import numpy as np
import pandas as pd

Expand Down Expand Up @@ -33,21 +34,25 @@ def get_pp_net_special_columns_dict() -> Dict[str, str]:

def extend_pp_net_cim(net: pandapowerNet, override: bool = True) -> pandapowerNet:
"""
Extend pandapower element DataFrames with special columns for the CIM converter, e.g. a column for the RDF ID.
:param net: The pandapower net to extend.
:param override: If True, all existing special CIM columns will be overwritten (content will be erased). If False,
only missing columns will be created. Optional, default: True
:return: The extended pandapower network.
Extend pandapower network with special element for the CIM converter.

..note::
The CIM converter creates a pandapower network with metadata key "cim".
See :func:`pandapower.network.pandapowerNet.__init__`

Parameters:
net: The pandapower net to extend.
override: If True, net.CGMES will be overwritten (content will be erased). If False,
only missing element will be created.

Returns:
Reference to the input pandapower network (input will be modified).
"""
# some special items
if override:
if 'CGMES' not in net or override:
net['CGMES'] = {}
if 'BaseVoltage' not in net['CGMES'] or override:
net['CGMES']['BaseVoltage'] = pd.DataFrame(None, columns=['rdfId', 'nominalVoltage'])
else:
if 'CGMES' not in net:
net['CGMES'] = {}
if 'BaseVoltage' not in net['CGMES']:
net['CGMES']['BaseVoltage'] = pd.DataFrame(None, columns=['rdfId', 'nominalVoltage'])

return net

Expand Down
Loading