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

devel_con_filter #285

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
bf6f385
Technical cost plot auto-scaling implemented for any grid
Jun 3, 2024
7bc8318
Technical cost plot auto-scaling implemented for any grid
Jun 3, 2024
f02bc12
Technical cost plot auto-scaling implemented for any grid
Jun 3, 2024
95c28e3
Technical cost plot auto-scaling implemented for any grid
Jun 3, 2024
5a73eb0
Technical cost plot auto-scaling implemented for any grid
Jun 3, 2024
b2d5bdd
gridcal_to_raw: branches, vsc_dc_lines, two_terminal_dc_lines, facts
peterkulik-navitasoft Jun 3, 2024
e556b2b
Merge remote-tracking branch 'refs/remotes/origin/204_investments_eva…
Jun 4, 2024
f1a9d77
Added the acopf to the docs tree
SanPen Jun 4, 2024
6f55d72
Merge branch '199_finalize_cgmes_import' into devel
SanPen Jun 4, 2024
02958ca
Merge branch '204_investments_evaluation' into devel
SanPen Jun 4, 2024
0d70bb1
Implemented the contingency_groups filtering by area, zone, country a…
SanPen Jun 4, 2024
5b3cf05
Corrected issue with overload indicators
Carlos-Alegre Jun 4, 2024
aaff838
Merge branch '202_nodal_capacity' into devel_con_filter
SanPen Jun 4, 2024
631716d
Further modifications to include the contingency group filtering in t…
SanPen Jun 4, 2024
2e5455d
better opf docstring
SanPen Jun 4, 2024
f1f8478
Refactored direct calls of contingency_groups
SanPen Jun 4, 2024
b3efacb
Further improvement on the contingency filtering
SanPen Jun 4, 2024
2d2d61b
Further improvement on the contingency filtering by sorting the conti…
SanPen Jun 4, 2024
c6de5f7
Schematic picture and video rendering working
SanPen Jun 4, 2024
dc96899
updated icon
Jun 4, 2024
dc42c3b
Fixed some bugs in the control of substations, voltage levels and lines
QuimMoya Jun 5, 2024
5f39a28
fixed mapwidget take picture
SanPen Jun 5, 2024
ce8f656
Merge branch '215-Mejorar-la-representación-de-red-en-los-mapas' into…
SanPen Jun 5, 2024
1268e36
Added minimal save-json file function that is commented out
SanPen Jun 5, 2024
5585c1e
Added tests
fernpos Jun 5, 2024
a905bb3
Improved schematic picture taking
SanPen Jun 5, 2024
460d918
Merge branch 'devel' into devel_con_filter
SanPen Jun 5, 2024
587e1e8
Finalized the contingency filtering test
SanPen Jun 5, 2024
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
152 changes: 57 additions & 95 deletions .idea/workspace.xml

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ branches = main_circuit.get_branches()
# manually generate the contingencies
for i, br in enumerate(branches):
# add a contingency group
group = ContingencyGroup(name="contingency {}".format(i+1))
group = ContingencyGroup(name="contingency {}".format(i + 1))
main_circuit.add_contingency_group(group)

# add the branch contingency to the groups, only groups are failed at once
Expand All @@ -809,17 +809,17 @@ for i, br in enumerate(branches):
# add a special contingency
group = ContingencyGroup(name="Special contingency")
main_circuit.add_contingency_group(group)
main_circuit.add_contingency(Contingency(device_idtag=branches[3].idtag,
main_circuit.add_contingency(Contingency(device_idtag=branches[3].idtag,
name=branches[3].name, group=group))
main_circuit.add_contingency(Contingency(device_idtag=branches[5].idtag,
main_circuit.add_contingency(Contingency(device_idtag=branches[5].idtag,
name=branches[5].name, group=group))

pf_options = PowerFlowOptions(solver_type=SolverType.NR)

# declare the contingency options
options_ = ContingencyAnalysisOptions(use_provided_flows=False,
Pf=None,
engine=ContingencyMethod.PowerFlow,
contingency_method=ContingencyMethod.PowerFlow,
# if no power flow options are provided
# a linear power flow is used
pf_options=pf_options)
Expand Down
1 change: 1 addition & 0 deletions doc/rst_source/theory/simulations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Optimal power flow
opf/opf
opf/opf_dc_ts
opf/opf_ac_ts
opf/acopf
opf/hydro


Expand Down
7 changes: 3 additions & 4 deletions examples/contingency_analysis_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,13 @@
# declare the contingency options
options_ = ContingencyAnalysisOptions(use_provided_flows=False,
Pf=None,
engine=en.ContingencyMethod.PowerFlow,
contingency_method=en.ContingencyMethod.PowerFlow,
pf_options=pf_options)

linear_multiple_contingencies = LinearMultiContingencies(grid=main_circuit)

simulation = ContingencyAnalysisDriver(grid=main_circuit,
options=options_,
linear_multiple_contingencies=linear_multiple_contingencies)
linear_multiple_contingencies=None # it is computed inside
)

simulation.run()

Expand Down
2 changes: 1 addition & 1 deletion examples/contingency_analysis_ts.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
options_ = ContingencyAnalysisOptions(
use_provided_flows=False,
Pf=None,
engine=en.ContingencyMethod.PTDF,
contingency_method=en.ContingencyMethod.PTDF,
pf_options=PowerFlowOptions(),
)

Expand Down
12 changes: 10 additions & 2 deletions src/GridCal/Gui/Diagrams/MapWidget/Schema/map_template_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ def update_connectors(self) -> None:
for conector in self.segments_list:
conector.update_endings()

def end_update(self) -> None:
"""

:return:
"""

for conector in self.segments_list:
conector.end_update()

def draw_all(self) -> None:
"""

Expand Down Expand Up @@ -198,8 +207,7 @@ def redraw_segments(self) -> None:
# Assuming Connector takes (scene, node1, node2) as arguments
segment_graphic_object = Segment(first=elm1, second=elm2)

elm1.needsUpdateFirst = True
elm2.needsUpdateSecond = True
elm2.needsUpdate = True
segment_graphic_object.needsUpdate = True

# register the segment in the line
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ def updatePosition(self):

if self.enabled:
self.updateRealPos()
self.needsUpdateFirst = True
self.needsUpdateSecond = True
self.needsUpdate = True
self.line_container.update_connectors()

def updateDiagram(self):
Expand Down
6 changes: 2 additions & 4 deletions src/GridCal/Gui/Diagrams/MapWidget/Schema/node_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,12 @@ class NodeTemplate:
"""

def __init__(self,
needsUpdateFirst: bool = True,
needsUpdateSecond: bool = True,
needsUpdate: bool = True,
lat: float = 0.0,
lon: float = 0.0):
"""
"""
self.needsUpdateFirst: bool = needsUpdateFirst
self.needsUpdateSecond: bool = needsUpdateSecond
self.needsUpdate: bool = needsUpdate
self.lat = lat
self.lon = lon

Expand Down
7 changes: 4 additions & 3 deletions src/GridCal/Gui/Diagrams/MapWidget/Schema/segment.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,13 @@ def update_endings(self) -> None:
"""

# Get the positions of the first and second objects
if self.first.needsUpdateFirst or self.second.needsUpdateSecond:
if self.first.needsUpdate or self.second.needsUpdate:
first_pos = self.first.getRealPos()
second_pos = self.second.getRealPos()

# Set the line's starting and ending points
self.setLine(first_pos[0], first_pos[1], second_pos[0], second_pos[1])

self.first.needsUpdateFirst = False
self.second.needsUpdateSecond = False
def end_update(self) -> None:
self.first.needsUpdate = False
self.second.needsUpdate = False
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,6 @@ def updatePosition(self):
self.x = center_point.x() + real_position.x()
self.y = center_point.y() + real_position.y()
self.needsUpdate = True
self.updateDiagram()

def updateDiagram(self):
"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ def updatePosition(self):
self.x = center_point.x() + real_position.x()
self.y = center_point.y() + real_position.y()
self.needsUpdate = True
self.updateDiagram()

def updateDiagram(self):
"""
Expand Down
77 changes: 56 additions & 21 deletions src/GridCal/Gui/Diagrams/MapWidget/grid_map_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import os
from typing import Union, List, Tuple
import cv2
import numpy as np
from PySide6.QtWidgets import QWidget, QGraphicsItem
from PySide6.QtCore import Qt
from PySide6.QtCore import Qt, QSize, QRect
from PySide6.QtGui import QColor
from collections.abc import Callable
from PySide6.QtGui import (QImage, QPainter)
from PySide6.QtSvg import QSvgGenerator

from GridCalEngine.Devices.Diagrams.map_location import MapLocation
from GridCalEngine.Devices.Substation import Bus
Expand Down Expand Up @@ -355,7 +357,6 @@ def merge_lines(self):
better_first.line_container.disable_line()
better_second.line_container.disable_line()


def create_line(self, api_object: BRANCH_TYPES, original: bool = True) -> MapTemplateLine:
"""
Adds a line with the nodes and segments
Expand Down Expand Up @@ -389,6 +390,9 @@ def update_connectors(self):
for idtag, graphic_object in dev_dict.items():
graphic_object.update_connectors()

for idtag, graphic_object in dev_dict.items():
graphic_object.end_update()

def create_substation(self,
api_object: Substation,
lat: float, lon: float,
Expand Down Expand Up @@ -668,7 +672,8 @@ def colour_results(self,
color = QColor(r, g, b, a)
style = Qt.SolidLine
if use_flow_based_width:
weight = int(np.floor(min_branch_width + Sfnorm[i] * (max_branch_width - min_branch_width) * 0.1))
weight = int(
np.floor(min_branch_width + Sfnorm[i] * (max_branch_width - min_branch_width) * 0.1))
else:
weight = 0.5

Expand Down Expand Up @@ -718,27 +723,58 @@ def colour_results(self,
color = QColor(r, g, b, a)
style = Qt.SolidLine
if use_flow_based_width:
weight = int(np.floor(min_branch_width + Sfnorm[i] * (max_branch_width - min_branch_width) * 0.1))
weight = int(
np.floor(min_branch_width + Sfnorm[i] * (max_branch_width - min_branch_width) * 0.1))
else:
weight = 0.5

graphic_object.set_colour(color=color, w=weight, style=style, tool_tip=tooltip)

def get_image(self, w: int, h: int) -> QImage:
def get_image(self) -> Tuple[QImage, int, int]:
"""
get the current picture
:return: QImage, width, height
"""
w = self.width()
h = self.height()

:param w:
:param h:
:return:
# image = QImage(w, h, QImage.Format_RGB32)
# image.fill(Qt.white)
#
# painter = QPainter(image)
# painter.setRenderHint(QPainter.Antialiasing)
# # self.view.render(painter) # self.view stores the grid widgets
# self.render(painter)
# painter.end()
image = self.grab().toImage()

return image, w, h

def take_picture(self, filename: str):
"""
image = QImage(w, h, QImage.Format_ARGB32_Premultiplied)
image.fill(Qt.transparent)
painter = QPainter(image)
painter.setRenderHint(QPainter.Antialiasing)
self.diagram_scene.render(painter)
painter.end()
Save the grid to a png file
"""
name, extension = os.path.splitext(filename.lower())

if extension == '.png':
image, _, _ = self.get_image(transparent=True)
image.save(filename)

return image
elif extension == '.svg':
w = self.width()
h = self.height()
svg_gen = QSvgGenerator()
svg_gen.setFileName(filename)
svg_gen.setSize(QSize(w, h))
svg_gen.setViewBox(QRect(0, 0, w, h))
svg_gen.setTitle("Electrical grid schematic")
svg_gen.setDescription("An SVG drawing created by GridCal")

painter = QPainter(svg_gen)
self.render(painter)
painter.end()
else:
raise Exception('Extension ' + str(extension) + ' not supported :(')

def start_video_recording(self, fname: str, fps: int = 30) -> Tuple[int, int]:
"""
Expand All @@ -758,17 +794,16 @@ def start_video_recording(self, fname: str, fps: int = 30) -> Tuple[int, int]:

return w, h

def capture_video_frame(self, w: int, h: int):
def capture_video_frame(self):
"""
Save video frame
"""

qimage = self.get_image(w=w, h=h)

ptr = qimage.convertToFormat(QImage.Format.Format_RGB32).constBits()

frame = np.array(ptr).reshape(h, w, 4) # Copies the data
image, w, h = self.get_image()

# convert picture using the memory
# we need to remove the alpha channel, otherwise the video frame is not saved
frame = np.array(image.constBits()).reshape(h, w, 4).astype(np.uint8)[:, :, :3]
self._video.write(frame)

def end_video_recording(self):
Expand Down
8 changes: 6 additions & 2 deletions src/GridCal/Gui/Diagrams/SchematicWidget/generic_graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
ACTIVE = {'style': Qt.SolidLine,
'color': Qt.white if IS_DARK else Qt.black,
'text': Qt.white if IS_DARK else Qt.black,
'backgound': Qt.black if IS_DARK else Qt.white,
'fluid': QColor(0, 170, 212, 255)}

DEACTIVATED = {'style': Qt.DashLine, 'color': Qt.gray}
Expand All @@ -61,6 +62,10 @@ def set_light_mode() -> None:
ACTIVE['text'] = Qt.black


def is_dark_mode() -> bool:
return IS_DARK


if IS_DARK:
set_dark_mode()
else:
Expand Down Expand Up @@ -171,6 +176,7 @@ class GenericDBWidget:
"""
Generic DataBase Widget
"""

def __init__(self,
parent,
api_object: ALL_DEV_TYPES,
Expand Down Expand Up @@ -254,5 +260,3 @@ def enable_disable_label_drawing(self):
:return:
"""
self.draw_labels = not self.draw_labels


Loading