Skip to content

Commit

Permalink
Buses and Equipment lists views (#6)
Browse files Browse the repository at this point in the history
Signed-off-by: Damien Jeandemange <damien.jeandemange@gmail.com>
  • Loading branch information
jeandemanged authored Nov 12, 2024
1 parent 4a3cfd0 commit 06e0d89
Show file tree
Hide file tree
Showing 25 changed files with 969 additions and 65 deletions.
16 changes: 8 additions & 8 deletions yagat/app_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,6 @@ def selected_view(self, value: str) -> None:
def network(self) -> Optional[pn.Network]:
return self._network

@property
def lf_parameters(self) -> lf.Parameters:
return self._lf_parameters

@property
def network_structure(self) -> Optional[ns.NetworkStructure]:
return self._network_structure

@network.setter
def network(self, new_network: Optional[pn.Network]) -> None:
self._network = new_network
Expand All @@ -85,6 +77,14 @@ def network(self, new_network: Optional[pn.Network]) -> None:
self.selection = (None, None, None)
self.notify_network_changed()

@property
def lf_parameters(self) -> lf.Parameters:
return self._lf_parameters

@property
def network_structure(self) -> Optional[ns.NetworkStructure]:
return self._network_structure

@property
def selection(self) -> tuple[Optional[str], Optional[str], Optional[ns.Connection]]:
return self._selection
Expand Down
2 changes: 1 addition & 1 deletion yagat/frames/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
#
from .impl.diagram_view import DiagramView
from .impl.load_flow_parameters import LoadFlowParametersView
from .impl.main_application import MainApplication
from .impl.splash_screen import SplashScreen
from .impl.status_bar import StatusBar
from .impl.tabs_view import TabsView
from .impl.tree_and_diagram import TreeAndDiagram
from .impl.tree_view import TreeView
78 changes: 78 additions & 0 deletions yagat/frames/impl/base_list_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#
# Copyright (c) 2024, Damien Jeandemange (https://github.com/jeandemanged)
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
#
import tkinter as tk
from abc import ABC, abstractmethod
from typing import Optional

import pandas as pd
import tksheet as tks

from yagat.app_context import AppContext
from yagat.networkstructure import Connection


class BaseListView(tk.Frame, ABC):

def __init__(self, parent, context: AppContext, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.sheet = tks.Sheet(self, index_align='left')
self.sheet.enable_bindings('single_select',
'drag_select',
'row_select',
'column_select',
'copy',
'column_width_resize',
'double_click_column_resize',
'double_click_row_resize',
'row_width_resize',
'column_height_resize',
'arrowkeys',
)
self.context = context
self.context.add_selection_changed_listener(self.on_selection_changed)

self.sheet.set_index_width(300)
self.sheet.pack(fill="both", expand=True)

@property
@abstractmethod
def tab_name(self) -> str:
pass

@abstractmethod
def get_data_frame(self) -> pd.DataFrame:
pass

@abstractmethod
def filter_data_frame(self, df: pd.DataFrame, voltage_levels: list[str]) -> pd.DataFrame:
pass

def on_selection_changed(self, selection: tuple[Optional[str], Optional[str], Optional[Connection]]):
if not self.context.network_structure:
self.sheet.data = []
return
df = self.get_data_frame()
voltage_levels = self.filtered_voltage_levels(selection)
if voltage_levels:
df = self.filter_data_frame(df, voltage_levels)
self.sheet.data = [l.tolist() for l in df.to_numpy()]
self.sheet.set_index_data(df.index.tolist())
self.sheet.set_header_data(df.columns)
self.sheet.set_all_cell_sizes_to_text()

def filtered_voltage_levels(self,
selection: tuple[Optional[str], Optional[str], Optional[Connection]]) -> list[str]:
voltage_levels: list[str] = []
if selection[0] == 'network' or not selection[0] or not selection[1]:
return voltage_levels
elif selection[0] == 'voltage_level':
voltage_levels = [selection[1]]
elif selection[0] == 'substation':
voltage_levels = [vl.voltage_level_id for vl in
self.context.network_structure.get_substation(selection[1]).voltage_levels]
return voltage_levels
48 changes: 48 additions & 0 deletions yagat/frames/impl/buses_bus_breaker_view_list_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#
# Copyright (c) 2024, Damien Jeandemange (https://github.com/jeandemanged)
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
#
import os
import tkinter as tk

import pandas as pd
import pypowsybl.network as pn

from yagat.app_context import AppContext
from yagat.frames.impl.base_list_view import BaseListView


class BusesBusBreakerViewListView(BaseListView):

def __init__(self, parent, context: AppContext, *args, **kwargs):
BaseListView.__init__(self, parent, context, *args, **kwargs)

@property
def tab_name(self) -> str:
return 'Buses (Bus/Breaker View)'

def get_data_frame(self) -> pd.DataFrame:
return self.context.network_structure.buses_bus_breaker_view

def filter_data_frame(self, df: pd.DataFrame, voltage_levels: list[str]) -> pd.DataFrame:
return df.loc[df['voltage_level_id'].isin(voltage_levels)]


if __name__ == "__main__":

if os.name == 'nt':
# Fixing the blur UI on Windows
from ctypes import windll

windll.shcore.SetProcessDpiAwareness(2)
root = tk.Tk()
ctx = AppContext(root)
bw = BusesBusBreakerViewListView(root, ctx)
bw.pack(fill="both", expand=True)
ctx.network = pn.create_ieee9()
ctx.selection = ('network', '', None)
ctx.selected_tab = bw.tab_name
root.mainloop()
48 changes: 48 additions & 0 deletions yagat/frames/impl/buses_bus_view_list_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#
# Copyright (c) 2024, Damien Jeandemange (https://github.com/jeandemanged)
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
#
import os
import tkinter as tk

import pandas as pd
import pypowsybl.network as pn

from yagat.app_context import AppContext
from yagat.frames.impl.base_list_view import BaseListView


class BusesListView(BaseListView):

def __init__(self, parent, context: AppContext, *args, **kwargs):
BaseListView.__init__(self, parent, context, *args, **kwargs)

@property
def tab_name(self) -> str:
return 'Buses (Bus View)'

def get_data_frame(self) -> pd.DataFrame:
return self.context.network_structure.buses

def filter_data_frame(self, df: pd.DataFrame, voltage_levels: list[str]) -> pd.DataFrame:
return df.loc[df['voltage_level_id'].isin(voltage_levels)]


if __name__ == "__main__":

if os.name == 'nt':
# Fixing the blur UI on Windows
from ctypes import windll

windll.shcore.SetProcessDpiAwareness(2)
root = tk.Tk()
ctx = AppContext(root)
bw = BusesListView(root, ctx)
bw.pack(fill="both", expand=True)
ctx.network = pn.create_ieee9()
ctx.selection = ('network', '', None)
ctx.selected_tab = bw.tab_name
root.mainloop()
48 changes: 48 additions & 0 deletions yagat/frames/impl/dangling_line_list_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#
# Copyright (c) 2024, Damien Jeandemange (https://github.com/jeandemanged)
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
#
import os
import tkinter as tk

import pandas as pd
import pypowsybl.network as pn

from yagat.app_context import AppContext
from yagat.frames.impl.base_list_view import BaseListView


class DanglingLineListView(BaseListView):

def __init__(self, parent, context: AppContext, *args, **kwargs):
BaseListView.__init__(self, parent, context, *args, **kwargs)

@property
def tab_name(self) -> str:
return 'Dangling Lines'

def get_data_frame(self) -> pd.DataFrame:
return self.context.network_structure.dangling_lines

def filter_data_frame(self, df: pd.DataFrame, voltage_levels: list[str]) -> pd.DataFrame:
return df.loc[df['voltage_level_id'].isin(voltage_levels)]


if __name__ == "__main__":

if os.name == 'nt':
# Fixing the blur UI on Windows
from ctypes import windll

windll.shcore.SetProcessDpiAwareness(2)
root = tk.Tk()
ctx = AppContext(root)
bw = DanglingLineListView(root, ctx)
bw.pack(fill="both", expand=True)
ctx.network = pn.create_micro_grid_be_network()
ctx.selection = ('network', '', None)
ctx.selected_tab = bw.tab_name
root.mainloop()
45 changes: 0 additions & 45 deletions yagat/frames/impl/diagram_view.py

This file was deleted.

4 changes: 3 additions & 1 deletion yagat/frames/impl/diagram_view_bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,16 @@ def tab_name(self) -> str:
return self._tab_name

def on_selection_changed(self, selection: tuple[Optional[str], Optional[str], Optional[Connection]]):
_, selection_id, selection_connection = selection
selection_type, selection_id, selection_connection = selection
selected_connection_y = 0
if self.context.selected_tab != self.tab_name:
return
logging.info('Start drawing bus view')
for w in self.widgets:
w.destroy()
self.widgets = []
if selection_type not in ['substation', 'voltage_level']:
return
if not selection_id:
return
if self.context.selected_tab != self.tab_name:
Expand Down
48 changes: 48 additions & 0 deletions yagat/frames/impl/generator_list_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#
# Copyright (c) 2024, Damien Jeandemange (https://github.com/jeandemanged)
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
#
import os
import tkinter as tk

import pandas as pd
import pypowsybl.network as pn

from yagat.app_context import AppContext
from yagat.frames.impl.base_list_view import BaseListView


class GeneratorListView(BaseListView):

def __init__(self, parent, context: AppContext, *args, **kwargs):
BaseListView.__init__(self, parent, context, *args, **kwargs)

@property
def tab_name(self) -> str:
return 'Generators'

def get_data_frame(self) -> pd.DataFrame:
return self.context.network_structure.generators

def filter_data_frame(self, df: pd.DataFrame, voltage_levels: list[str]) -> pd.DataFrame:
return df.loc[df['voltage_level_id'].isin(voltage_levels)]


if __name__ == "__main__":

if os.name == 'nt':
# Fixing the blur UI on Windows
from ctypes import windll

windll.shcore.SetProcessDpiAwareness(2)
root = tk.Tk()
ctx = AppContext(root)
bw = GeneratorListView(root, ctx)
bw.pack(fill="both", expand=True)
ctx.network = pn.create_ieee9()
ctx.selection = ('network', '', None)
ctx.selected_tab = bw.tab_name
root.mainloop()
Loading

0 comments on commit 06e0d89

Please sign in to comment.