From 4f3171b9cace5c335f46bef3cde0e2bf395b3d20 Mon Sep 17 00:00:00 2001 From: Christian Biasuzzi Date: Thu, 27 Jun 2024 19:58:28 +0200 Subject: [PATCH] adds parameters for displaying ids or names, and filter the top n nominal vls in the map widget; network explorer: activates the SLD tab when a VL level is chosen in the map tab Signed-off-by: Christian Biasuzzi --- js/networkmapwidget.jsx | 28 ++++++++++++++++++++--- js/voltage-level-choice.jsx | 19 ++------------- src/pypowsybl_jupyter/networkexplorer.py | 7 ++++-- src/pypowsybl_jupyter/networkmapwidget.py | 22 ++++++++++++++---- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/js/networkmapwidget.jsx b/js/networkmapwidget.jsx index 3716e1a..345bee3 100644 --- a/js/networkmapwidget.jsx +++ b/js/networkmapwidget.jsx @@ -17,7 +17,6 @@ import { Box } from '@mui/system'; const INITIAL_ZOOM = 9; const LABELS_ZOOM_THRESHOLD = 9; const ARROWS_ZOOM_THRESHOLD = 7; -const useName = true; const styles = { divNominalVoltageFilter: { @@ -82,7 +81,11 @@ const render = createRender(() => { const [smap] = useModelState('smap'); const [lmap] = useModelState('lmap'); + const [use_name] = useModelState('use_name'); + const [params, setParams] = useModelState('params'); + const [nvls] = useModelState('nvls'); + const targetSubId = params['subId']; const [centerOnSubId, setCenterOnSubId] = useState( targetSubId === null ? null : { to: targetSubId } @@ -160,6 +163,23 @@ const render = createRender(() => { [] ); + const useNameOrId = () => { + const useName = use_name; + const getNameOrId = useCallback( + (infos) => { + if (infos != null) { + const name = infos.name; + return useName && name != null && name.trim() !== '' + ? name + : infos?.id; + } + return null; + }, + [useName] + ); + return { getNameOrId }; + }; + function renderVoltageLevelChoice() { return ( { onClickHandler={choiceVoltageLevel} substation={choiceVoltageLevelsSubstation} position={[position[0], position[1]]} + useNameOrId={useNameOrId} /> ); } - const [filteredNominalVoltages, setFilteredNominalVoltages] = useState(); + const [filteredNominalVoltages, setFilteredNominalVoltages] = + useState(nvls); function renderNominalVoltageFilter() { return ( @@ -193,7 +215,7 @@ const render = createRender(() => { labelsZoomThreshold={LABELS_ZOOM_THRESHOLD} arrowsZoomThreshold={ARROWS_ZOOM_THRESHOLD} initialZoom={INITIAL_ZOOM} - useName={useName} + useName={use_name} centerOnSubstation={centerOnSubId} onSubstationClick={(vlId) => { console.log('# OpenVoltageLevel: ' + vlId); diff --git a/js/voltage-level-choice.jsx b/js/voltage-level-choice.jsx index 90e5acd..6e6284b 100644 --- a/js/voltage-level-choice.jsx +++ b/js/voltage-level-choice.jsx @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import React, { useCallback } from 'react'; +import React from 'react'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; import ListItemIcon from '@mui/material/ListItemIcon'; @@ -41,22 +41,6 @@ const styles = { }, }; -const useNameOrId = (useName) => { - const getNameOrId = useCallback( - (infos) => { - if (infos != null) { - const name = infos.name; - return useName && name != null && name.trim() !== '' - ? name - : infos?.id; - } - return null; - }, - [useName] - ); - return { getNameOrId }; -}; - const voltageLevelComparator = (vl1, vl2) => { return vl1.nominalV < vl2.nominalV; }; @@ -84,6 +68,7 @@ const VoltageLevelChoice = ({ onClickHandler, substation, position, + useNameOrId, }) => { const { getNameOrId } = useNameOrId(); diff --git a/src/pypowsybl_jupyter/networkexplorer.py b/src/pypowsybl_jupyter/networkexplorer.py index 2c5a904..8e86911 100644 --- a/src/pypowsybl_jupyter/networkexplorer.py +++ b/src/pypowsybl_jupyter/networkexplorer.py @@ -12,7 +12,7 @@ import ipywidgets as widgets -def network_explorer(network: Network, vl_id : str = None, depth: int = 0, high_nominal_voltage_bound: float = -1, low_nominal_voltage_bound: float = -1, nad_parameters: NadParameters = None, sld_parameters: SldParameters = None): +def network_explorer(network: Network, vl_id : str = None, depth: int = 0, high_nominal_voltage_bound: float = -1, low_nominal_voltage_bound: float = -1, nad_parameters: NadParameters = None, sld_parameters: SldParameters = None, nominal_voltages_top_tiers_filter:int = -1): """ Creates a combined NAD and SLD explorer widget for the network. Diagrams are displayed on two different tabs. @@ -24,6 +24,7 @@ def network_explorer(network: Network, vl_id : str = None, depth: int = 0, high_ high_nominal_voltage_bound: high bound to filter voltage level according to nominal voltage nad_parameters: layout properties to adjust the svg rendering for the NAD sld_parameters: layout properties to adjust the svg rendering for the SLD + nominal_voltages_top_tiers_filter: number of nominal voltages to select in the nominal voltages filter, starting from the highest (map viewer tab) Examples: @@ -81,6 +82,8 @@ def go_to_vl_from_map(event: any): found.options=vl_filtered_list selected_vl=vl_from_map found.value=vl_from_map + #move to the SLD tab + tabs_diagrams.selected_index=1 def update_nad_diagram(): nonlocal nad_widget @@ -107,7 +110,7 @@ def update_map(): nonlocal map_widget if selected_vl is not None: if map_widget==None: - map_widget=NetworkMapWidget(network) + map_widget=NetworkMapWidget(network, nominal_voltages_top_tiers_filter = nominal_voltages_top_tiers_filter) map_widget.on_selectvl(lambda event : go_to_vl_from_map(event)) else: diff --git a/src/pypowsybl_jupyter/networkmapwidget.py b/src/pypowsybl_jupyter/networkmapwidget.py index d6e0896..f8256e8 100644 --- a/src/pypowsybl_jupyter/networkmapwidget.py +++ b/src/pypowsybl_jupyter/networkmapwidget.py @@ -25,11 +25,16 @@ class NetworkMapWidget(anywidget.AnyWidget): smap = traitlets.Unicode().tag(sync=True) lmap = traitlets.Unicode().tag(sync=True) - params = traitlets.Dict().tag(sync=True) + use_name = traitlets.Bool().tag(sync=True) + + nvls = traitlets.List().tag(sync=True) + params = traitlets.Dict().tag(sync=True) + selected_vl = traitlets.Unicode().tag(sync=True) + - def __init__(self, network, subId = None, display_lines:bool = True, use_line_extensions = False, **kwargs): + def __init__(self, network, subId = None, use_name:bool = True, display_lines:bool = True, use_line_extensions = False, nominal_voltages_top_tiers_filter = -1, **kwargs): super().__init__(**kwargs) (lmap, lpos, smap, spos, vl_subs, sub_vls, subs_ids) = self.extract_map_data(network, display_lines, use_line_extensions) @@ -37,10 +42,12 @@ def __init__(self, network, subId = None, display_lines:bool = True, use_line_ex self.lpos=json.dumps(lpos) self.smap=json.dumps(smap) self.spos=json.dumps(spos) + self.use_name=use_name self.params={"subId": subId} self.vl_subs=vl_subs self.sub_vls=sub_vls self.subs_ids=subs_ids + self.nvls=self.extract_nominal_voltage_list(network, nominal_voltages_top_tiers_filter) self._on_selectvl_handlers = CallbackDispatcher() super().on_msg(self._handle_pw_msg) @@ -70,7 +77,7 @@ def center_on_voltage_level(self, vl_id): if sub_id is not None: self.params = {"subId": sub_id} - def extract_map_data(self, network, display_lines: bool = True, use_line_extensions = False): + def extract_map_data(self, network, display_lines, use_line_extensions): lmap = [] lpos = [] smap = [] @@ -136,10 +143,11 @@ def extract_map_data(self, network, display_lines: bool = True, use_line_extensi for s_id, group in vls_subs_df.groupby('substation_id'): entry = { "id": s_id, - "name": group['name_x'].iloc[0], # name from df1 + "name": group['name_y'].iloc[0], # name from df1 "voltageLevels": [ { "id": row['id'], # id from df2 + "name": row['name_x'], "substationId": row['substation_id'], "nominalV": row['nominal_v'] } for _, row in group.iterrows() @@ -164,3 +172,9 @@ def extract_map_data(self, network, display_lines: bool = True, use_line_extensi return (lmap, lpos, smap, spos, vl_subs, sub_vls, subs_ids) + def extract_nominal_voltage_list(self, network, nvls_top_tiers): + nvls_filtered = [] + nvls_filtered = sorted(network.get_voltage_levels()['nominal_v'].unique(), reverse=True) + if nvls_top_tiers != -1 : + nvls_filtered = nvls_filtered[:nvls_top_tiers] + return nvls_filtered \ No newline at end of file