Skip to content

Commit

Permalink
Merge branch 'develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
rbolgaryn authored Nov 8, 2023
2 parents 4fcb647 + d8e128e commit 766d4ed
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 28 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/github_test_action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Install Julia
if: ${{ matrix.python-version == '3.9' }}
run: |
./.install_julia.sh 1.8
./.install_julia.sh 1.9.3
pip install julia
python ./.install_pycall.py
- name: List of installed packages
Expand Down Expand Up @@ -181,7 +181,7 @@ jobs:
run: |
python -m pip install --upgrade pip
python -m pip install pytest nbmake pytest-xdist igraph numba seaborn
./.install_julia.sh 1.8
./.install_julia.sh 1.9.3
python -m pip install julia
python ./.install_pycall.py
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Change Log
- [FIXED] bug in coords conversion in cim2pp, small fixes
- [CHANGED] cim2pp: added support for multi diagram usage for DL profiles
- [CHANGED] cim2pp: made build_pp_net modular by introducing classes
- [ADDED] cim2pp: added option to opt out of internal powerflow calculation
- [FIXED] error handling in :code:`plotly/mapbox_plot.py` not raising :code`ImportError` if :code:`geopy` or :code:`pyproj` are missing
- [FIXED] powerfactory2pandapower-converter error if a line has two identical coordinates
- [ADDED] logger messages about the probabilistic load flow calculation (simultaneities) in the powerfactory2pandapower-converter for low voltage loads
Expand Down
34 changes: 21 additions & 13 deletions pandapower/converter/cim/cim2pp/build_pp_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,19 +170,22 @@ def convert_to_pp(self, convert_line_to_switch: bool = False, line_r_limit: floa
self.logger.info("Running a power flow.")
self.report_container.add_log(Report(
level=LogLevel.INFO, code=ReportCode.INFO, message="Running a power flow."))
try:
pp.runpp(self.net)
except Exception as e:
self.logger.error("Failed running a powerflow.")
self.logger.exception(e)
self.report_container.add_log(Report(
level=LogLevel.ERROR, code=ReportCode.ERROR, message="Failed running a powerflow."))
self.report_container.add_log(Report(level=LogLevel.EXCEPTION, code=ReportCode.EXCEPTION,
message=traceback.format_exc()))
else:
self.logger.info("Power flow solved normal.")
self.report_container.add_log(Report(
level=LogLevel.INFO, code=ReportCode.INFO, message="Power flow solved normal."))
if kwargs.get('run_powerflow', False):
try:
pp.runpp(self.net)
except Exception as e:
self.logger.error("Failed running a powerflow.")
self.logger.exception(e)
self.report_container.add_log(Report(
level=LogLevel.ERROR, code=ReportCode.ERROR, message="Failed running a powerflow."))
self.report_container.add_log(Report(level=LogLevel.EXCEPTION, code=ReportCode.EXCEPTION,
message=traceback.format_exc()))
if not kwargs.get('ignore_errors', True):
raise e
else:
self.logger.info("Power flow solved normal.")
self.report_container.add_log(Report(
level=LogLevel.INFO, code=ReportCode.INFO, message="Power flow solved normal."))
try:
create_measurements = kwargs.get('create_measurements', None)
if create_measurements is not None and create_measurements.lower() == 'sv':
Expand All @@ -206,7 +209,10 @@ def convert_to_pp(self, convert_line_to_switch: bool = False, line_r_limit: floa
level=LogLevel.EXCEPTION, code=ReportCode.EXCEPTION_CONVERTING,
message=traceback.format_exc()))
self.net.measurement = self.net.measurement[0:0]
if not kwargs.get('ignore_errors', True):
raise e
try:
# TODO: think on whether to remove whole function
if kwargs.get('update_assets_from_sv', False):
CreateMeasurements(self.net, self.cim).update_assets_from_sv()
except Exception as e:
Expand All @@ -218,6 +224,8 @@ def convert_to_pp(self, convert_line_to_switch: bool = False, line_r_limit: floa
self.report_container.add_log(Report(
level=LogLevel.EXCEPTION, code=ReportCode.EXCEPTION_CONVERTING,
message=traceback.format_exc()))
if not kwargs.get('ignore_errors', True):
raise e
# a special fix for BB and NB mixed networks:
# fuse boundary ConnectivityNodes with their TopologicalNodes
bus_t = self.net.bus.reset_index(level=0, drop=False)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ def _prepare_trafos_cim16(self, power_trafo2w: pd.DataFrame) -> pd.DataFrame:
one_item + '_lv']
del copy_list, one_item
# detect on which winding a tap changer is attached
power_trafo2w['tap_side'] = None
power_trafo2w.loc[power_trafo2w['step_lv'].notna(), 'tap_side'] = 'lv'
power_trafo2w.loc[power_trafo2w['step'].notna(), 'tap_side'] = 'hv'
fillna_list = ['neutralStep', 'lowStep', 'highStep', 'stepVoltageIncrement', 'stepPhaseShiftIncrement', 'step',
Expand Down Expand Up @@ -516,6 +517,7 @@ def _prepare_trafo3w_cim16(self, power_trafo3w: pd.DataFrame) -> pd.DataFrame:
del copy_list, one_item

# detect on which winding a tap changer is attached
power_trafo3w['tap_side'] = None
power_trafo3w.loc[power_trafo3w['step_lv'].notna(), 'tap_side'] = 'lv'
power_trafo3w.loc[power_trafo3w['step_mv'].notna(), 'tap_side'] = 'mv'
power_trafo3w.loc[power_trafo3w['step'].notna(), 'tap_side'] = 'hv'
Expand Down
20 changes: 12 additions & 8 deletions pandapower/converter/cim/cim2pp/from_cim.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,22 +95,26 @@ def from_cim(file_list: List[str] = None, encoding: str = 'utf-8', convert_line_
"""
Convert a CIM net to a pandapower net from XML files.
Additional parameters for kwargs:
create_measurements (str): Set this parameter to 'SV' to create measurements for the pandapower net from the SV
- create_measurements (str): Set this parameter to 'SV' to create measurements for the pandapower net from the SV
profile. Set it to 'Analog' to create measurements from Analogs. If the parameter is not set or is set to None, no
measurements will be created.
update_assets_from_sv (bool): Set this parameter to True to update the assets (sgens, loads, wards, ...) with values
from the SV profile. Default: False.
use_GL_or_DL_profile (str): Choose the profile to use for converting coordinates. Set it to 'GL' to use the GL
- update_assets_from_sv (bool): Set this parameter to True to update the assets (sgens, loads, wards, ...) with
values from the SV profile. Default: False.
- use_GL_or_DL_profile (str): Choose the profile to use for converting coordinates. Set it to 'GL' to use the GL
profile (Usually lat and long coordinates). Set it to 'DL' to use the DL profile (Usually x, y coordinates for
displaying control room schema). Set it to 'both' to let the converter choose the profile. The converter will
choose the GL profile first if available, otherwise the DL profile. Optional, default: both.
diagram_name (str): The name from the Diagram from the diagram layout profile for the geo coordinates. Default: The
first diagram sorted ascending by name. Set the parameter to "all" to use available diagrams for creating the
- diagram_name (str): The name from the Diagram from the diagram layout profile for the geo coordinates. Default:
The first diagram sorted ascending by name. Set the parameter to "all" to use available diagrams for creating the
coordinates.
create_tap_controller (bool): If True, create pandapower controllers for transformer tap changers. If False, skip
- create_tap_controller (bool): If True, create pandapower controllers for transformer tap changers. If False, skip
creating them. Default: True
sn_mva (float): Set the sn_mva from the pandapower net to a specific value. This value is not given in CGMES.
- sn_mva (float): Set the sn_mva from the pandapower net to a specific value. This value is not given in CGMES.
Default: None (pandapower default will be chosen)
- run_powerflow (bool): Option to run to powerflow inside the converter to create res tables directly.
Default: False.
- ignore_errors (bool): Option to disable raising of internal errors. Useful if you need to get a network not matter
if there are errors in the conversion. Default: True.
:param file_list: The path to the CGMES files as a list.
:param encoding: The encoding from the files. Optional, default: utf-8
Expand Down
21 changes: 18 additions & 3 deletions pandapower/test/converter/test_from_cim.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def SimBench_1_HVMVmixed_1_105_0_sw_modified():

cgmes_files = [os.path.join(folder_path, 'SimBench_1-HVMV-mixed-1.105-0-sw_modified.zip')]

return cim2pp.from_cim(file_list=cgmes_files)
return cim2pp.from_cim(file_list=cgmes_files, run_powerflow=True)


@pytest.fixture(scope="session")
Expand All @@ -63,7 +63,7 @@ def Simbench_1_EHV_mixed__2_no_sw():

cgmes_files = [os.path.join(folder_path, 'Simbench_1-EHV-mixed--2-no_sw.zip')]

return cim2pp.from_cim(file_list=cgmes_files, create_measurements='SV')
return cim2pp.from_cim(file_list=cgmes_files, create_measurements='SV', run_powerflow=True)


@pytest.fixture(scope="session")
Expand All @@ -77,6 +77,20 @@ def example_multivoltage():
return net


@pytest.fixture(scope="session")
def SimBench_1_HVMVmixed_1_105_0_sw_modified_no_load_flow():
folder_path = os.path.join(test_path, "test_files", "example_cim")

cgmes_files = [os.path.join(folder_path, 'SimBench_1-HVMV-mixed-1.105-0-sw_modified.zip')]

return cim2pp.from_cim(file_list=cgmes_files)


def test_SimBench_1_HVMVmixed_1_105_0_sw_modified_no_load_flow_res_bus(
SimBench_1_HVMVmixed_1_105_0_sw_modified_no_load_flow):
assert 0 == len(SimBench_1_HVMVmixed_1_105_0_sw_modified_no_load_flow.res_bus.index)


def test_example_multivoltage_res_xward(example_multivoltage):
assert 2 == len(example_multivoltage.res_xward.index)
element_0 = example_multivoltage.res_xward.iloc[example_multivoltage.xward[
Expand Down Expand Up @@ -715,7 +729,7 @@ def test_fullgrid_trafo(fullgrid):
assert 0.0 == element_1['pfe_kw'].item()
assert 0.0 == element_1['i0_percent'].item()
assert 0.0 == element_1['shift_degree'].item()
assert math.isnan(element_1['tap_side'].item())
assert None is element_1['tap_side'].item()
assert pd.isna(element_1['tap_neutral'].item())
assert pd.isna(element_1['tap_min'].item())
assert pd.isna(element_1['tap_max'].item())
Expand Down Expand Up @@ -1054,6 +1068,7 @@ def test_fullgrid_controller(fullgrid):
def test_fullgrid_characteristic_temp(fullgrid):
assert 8 == len(fullgrid.characteristic_temp.index)


def test_fullgrid_characteristic(fullgrid):
assert 20 == len(fullgrid.characteristic.index)
for _, obj in fullgrid.characteristic.iterrows():
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"deepdiff"],
extras_require={
"docs": ["numpydoc", "sphinx", "sphinx_rtd_theme"],
"plotting": ["plotly", "matplotlib", "igraph", "geopandas", "geojson"],
"plotting": ["plotly", "matplotlib", "python-igraph", "geopandas", "geojson"],
# "shapely", "pyproj" are dependencies of geopandas and so already available;
# "base64", "hashlib", "zlib" produce installing problems, so they are not included
"test": ["pytest<=7.0", "pytest-xdist"],
Expand All @@ -62,7 +62,7 @@
# "fiona" is a depedency of geopandas and so already available
"converter": ["matpowercaseframes"],
"all": ["numpydoc", "sphinx", "sphinx_rtd_theme",
"plotly>=3.1.1", "matplotlib", "igraph", "geopandas", "geojson",
"plotly>=3.1.1", "matplotlib", "python-igraph", "geopandas", "geojson",
"pytest<=7.0", "pytest-xdist",
"ortools", # lightsim2grid,
"xlsxwriter", "openpyxl", "cryptography",
Expand Down

0 comments on commit 766d4ed

Please sign in to comment.