Skip to content

Commit

Permalink
adds a history section to the explorer. improve explorer's elements a…
Browse files Browse the repository at this point in the history
…lignments and sizes.

Signed-off-by: Christian Biasuzzi <[email protected]>
  • Loading branch information
CBiasuzzi committed Aug 1, 2024
1 parent ef08cac commit f764dba
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 37 deletions.
6 changes: 3 additions & 3 deletions js/sldwidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ function render({ model, el }: RenderProps<SldWidgetModel>) {
svg_data,
metadata ? JSON.parse(metadata) : null,
'voltage-level',
500,
800,
600,
800,
600,
1000,
1200,
metadata ? handleNextVl : null, //callback on the next voltage arrows
metadata ? handleSwitch : null, //callback on the breakers
metadata ? handleFeeder : null, //callback on the feeders
Expand Down
104 changes: 72 additions & 32 deletions src/pypowsybl_jupyter/networkexplorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def network_explorer(network: Network, vl_id : str = None, use_name:bool = True,
network_explorer(pp.network.create_eurostag_tutorial_example1_network())
"""

sel_ctx=SelectContext(network, vl_id, use_name)
sel_ctx=SelectContext(network, vl_id, use_name, history_max_length = 10)

nad_widget=None
sld_widget=None
Expand All @@ -56,34 +56,32 @@ def network_explorer(network: Network, vl_id : str = None, use_name:bool = True,

def go_to_vl(event: any):
arrow_vl= str(event.clicked_nextvl)
sel_ctx.extend_filtered_vls(arrow_vl)
found.value=None
found.options=sel_ctx.get_filtered_vls_as_list()
sel_ctx.set_selected(arrow_vl)
found.value=sel_ctx.get_selected()
update_explorer()


def toggle_switch(event: any):
idswitch = event.clicked_switch.get('id')
statusswitch = event.clicked_switch.get('switch_status')
network.update_switches(id=idswitch, open=statusswitch)
update_sld_diagram(True)
update_nad_diagram()
update_sld_diagram(sel_ctx.get_selected(), True)
update_nad_diagram(sel_ctx.get_selected())

def update_nad_diagram():
def update_nad_diagram(el):
nonlocal nad_widget
if sel_ctx.get_selected() is not None:
new_diagram_data=network.get_network_area_diagram(voltage_level_ids=sel_ctx.get_selected(),
if el is not None:
new_diagram_data=network.get_network_area_diagram(voltage_level_ids=el,
depth=selected_depth, high_nominal_voltage_bound=high_nominal_voltage_bound,
low_nominal_voltage_bound=low_nominal_voltage_bound, nad_parameters=npars)
if nad_widget==None:
nad_widget=display_nad(new_diagram_data)
else:
update_nad(nad_widget,new_diagram_data)

def update_sld_diagram(kv: bool = False):
def update_sld_diagram(el, kv: bool = False):
nonlocal sld_widget
if sel_ctx.get_selected() is not None:
sld_diagram_data=network.get_single_line_diagram(sel_ctx.get_selected(), spars)
if el is not None:
sld_diagram_data=network.get_single_line_diagram(el, spars)
if sld_widget==None:
sld_widget=display_sld(sld_diagram_data, enable_callbacks=True)
sld_widget.on_nextvl(lambda event: go_to_vl(event))
Expand All @@ -98,7 +96,7 @@ def update_sld_diagram(kv: bool = False):
def on_nadslider_changed(d):
nonlocal selected_depth
selected_depth=d['new']
update_nad_diagram()
update_nad_diagram(sel_ctx.get_selected())

nadslider.observe(on_nadslider_changed, names='value')

Expand All @@ -108,16 +106,30 @@ def on_nadslider_changed(d):
description='Filter',
disabled=False,
continuous_update=True,
layout=widgets.Layout(width='350px')
layout=widgets.Layout(flex='2%', height='100%', width='350px', margin='1px 0 0 0')
)

def update_select_widget(widget, el, elements=None, on_select=None):
if on_select:
widget.unobserve(on_select, names='value')
try:
if elements is not None:
widget.value = None
widget.options = elements

widget.value = el

finally:
if on_select:
widget.observe(on_select, names='value')


def on_text_changed(d):
nonlocal found
sel_ctx.apply_filter(d['new'])
found.value=None
found.options = sel_ctx.get_filtered_vls_as_list()
if sel_ctx.is_selected_in_filtered_vls():
found.value=sel_ctx.get_selected()
sel = sel_ctx.get_selected() if sel_ctx.is_selected_in_filtered_vls() else None
opts = sel_ctx.get_filtered_vls_as_list()
update_select_widget(found, sel, opts, on_selected)

vl_input.observe(on_text_changed, names='value')

Expand All @@ -126,32 +138,60 @@ def on_text_changed(d):
value=sel_ctx.get_selected(),
description='Found',
disabled=False,
layout=widgets.Layout(width='350px', height='670px')
layout=widgets.Layout(flex='80%', height='100%', width='350px', margin='0 0 0 0')
)

def on_selected(d):
if d['new'] != None:
sel_ctx.set_selected(d['new'])
update_nad_diagram()
update_sld_diagram()
update_explorer()

found.observe(on_selected, names='value')

update_nad_diagram()
update_sld_diagram()
history = widgets.Select(
options=sel_ctx.get_history_as_list(),
value=sel_ctx.get_selected(),
description='History',
disabled=False,
layout=widgets.Layout(flex='18%', height='100%', width='350px', margin='1px 0 0 0')
)

def on_selected_history(d):
if d['new'] != None:
sel_ctx.set_selected(d['new'])
update_explorer()

history.observe(on_selected_history, names='value')

def update_explorer():
sel=sel_ctx.get_selected()

update_select_widget(found, sel if sel_ctx.is_selected_in_filtered_vls() else None, None, on_selected)
update_select_widget(history, sel, sel_ctx.get_history_as_list(), on_selected_history)

update_nad_diagram(sel)
update_sld_diagram(sel)


update_nad_diagram(sel_ctx.get_selected())
update_sld_diagram(sel_ctx.get_selected())

voltage_levels_label=widgets.Label("Voltage levels")
spacer_label=widgets.Label("")

left_panel = widgets.VBox([vl_input, found, history], layout=widgets.Layout(width='100%', height='100%', display='flex', flex_flow='column'))

left_panel = widgets.VBox([widgets.Label('Voltage levels'), vl_input, found])

right_panel_nad = widgets.VBox([nadslider, nad_widget])
right_panel_sld = widgets.HBox([sld_widget])
right_panel_sld = widgets.VBox([spacer_label,sld_widget])

tabs_diagrams = widgets.Tab()
tabs_diagrams.children = [right_panel_nad, right_panel_sld]
tabs_diagrams.titles = ['Network Area', 'Single Line']
tabs_diagrams.layout=widgets.Layout(width='850px', height='700px')

hbox = widgets.HBox([left_panel, tabs_diagrams])
hbox.layout.align_items='flex-end'
tabs_diagrams.layout=widgets.Layout(width='850px', height='700px', margin='0 0 0 4px')

left_vbox = widgets.VBox([voltage_levels_label, left_panel])
right_vbox = widgets.VBox([spacer_label, tabs_diagrams])

hbox = widgets.HBox([left_vbox, right_vbox])

return hbox

19 changes: 17 additions & 2 deletions src/pypowsybl_jupyter/selectcontext.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
# SPDX-License-Identifier: MPL-2.0
#

from collections import OrderedDict
import pandas as pd
from collections import deque
from pypowsybl.network import Network

class SelectContext:

def __init__(self, network:Network = None, vl_id : str = None, use_name:bool = True):
def __init__(self, network:Network = None, vl_id : str = None, use_name:bool = True, history_max_length:int = -1):
self.network = network
self.use_name = use_name
self.display_attribute = 'name' if use_name else 'id'
Expand All @@ -24,6 +24,8 @@ def __init__(self, network:Network = None, vl_id : str = None, use_name:bool = T

self.apply_filter(None)

self.history = deque(maxlen=None if history_max_length == -1 else history_max_length)

self.set_selected(self.vls.index[0] if vl_id is None else vl_id)

def get_vls(self):
Expand All @@ -32,6 +34,7 @@ def get_vls(self):
def set_selected(self, id):
if id in self.vls.index:
self.selected_vl = id
self.add_to_history(id)
else:
raise ValueError(f'a voltage level with id={id} does not exist in the network.')

Expand All @@ -54,3 +57,15 @@ def get_filtered_vls_as_list(self):
def extend_filtered_vls(self, id):
if (id in self.vls.index) and (id not in self.vls_filtered.index):
self.vls_filtered = pd.concat([self.vls_filtered, self.vls.loc[[id]]])

def add_to_history(self, id):
if (id in self.vls.index):
row_to_add = self.vls.loc[id].to_dict()
for item in self.history:
if item['id'] == row_to_add['id']:
self.history.remove(item)
break
self.history.appendleft(row_to_add)

def get_history_as_list(self):
return [(item[self.display_attribute], item['id']) for item in self.history]

0 comments on commit f764dba

Please sign in to comment.