power-grid-model-ds 1.4.2__py3-none-any.whl → 1.4.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. power_grid_model_ds/_core/fancypy.py +7 -5
  2. power_grid_model_ds/_core/model/arrays/base/array.py +1 -1
  3. power_grid_model_ds/_core/model/arrays/pgm_arrays.py +21 -1
  4. power_grid_model_ds/_core/model/graphs/models/base.py +2 -5
  5. power_grid_model_ds/_core/visualizer/app.py +4 -2
  6. power_grid_model_ds/_core/visualizer/callbacks/config.py +66 -0
  7. power_grid_model_ds/_core/visualizer/callbacks/header.py +30 -0
  8. power_grid_model_ds/_core/visualizer/callbacks/search_form.py +8 -6
  9. power_grid_model_ds/_core/visualizer/layout/cytoscape_html.py +0 -2
  10. power_grid_model_ds/_core/visualizer/layout/header.py +49 -18
  11. power_grid_model_ds/_core/visualizer/layout/header_config.py +71 -0
  12. power_grid_model_ds/_core/visualizer/layout/header_legenda.py +36 -0
  13. power_grid_model_ds/_core/visualizer/layout/{search_form.py → header_search.py} +12 -18
  14. power_grid_model_ds/_core/visualizer/parsers.py +6 -7
  15. power_grid_model_ds/_core/visualizer/typing.py +7 -0
  16. {power_grid_model_ds-1.4.2.dist-info → power_grid_model_ds-1.4.4.dist-info}/METADATA +2 -2
  17. {power_grid_model_ds-1.4.2.dist-info → power_grid_model_ds-1.4.4.dist-info}/RECORD +20 -20
  18. power_grid_model_ds/_core/model/utils.py +0 -22
  19. power_grid_model_ds/_core/visualizer/callbacks/element_scaling.py +0 -37
  20. power_grid_model_ds/_core/visualizer/callbacks/layout_dropdown.py +0 -11
  21. power_grid_model_ds/_core/visualizer/layout/cytoscape_config.py +0 -54
  22. power_grid_model_ds/_core/visualizer/layout/legenda.py +0 -41
  23. {power_grid_model_ds-1.4.2.dist-info → power_grid_model_ds-1.4.4.dist-info}/WHEEL +0 -0
  24. {power_grid_model_ds-1.4.2.dist-info → power_grid_model_ds-1.4.4.dist-info}/licenses/LICENSE +0 -0
  25. {power_grid_model_ds-1.4.2.dist-info → power_grid_model_ds-1.4.4.dist-info}/top_level.txt +0 -0
@@ -4,7 +4,7 @@
4
4
 
5
5
  """A set of helper functions that mimic numpy functions but are specifically designed for FancyArrays."""
6
6
 
7
- from typing import TYPE_CHECKING, Union
7
+ from typing import TYPE_CHECKING, TypeVar, Union
8
8
 
9
9
  import numpy as np
10
10
 
@@ -13,8 +13,10 @@ from power_grid_model_ds._core.utils.misc import array_equal_with_nan
13
13
  if TYPE_CHECKING:
14
14
  from power_grid_model_ds._core.model.arrays.base.array import FancyArray
15
15
 
16
+ T = TypeVar("T", bound="FancyArray")
16
17
 
17
- def concatenate(fancy_array: "FancyArray", *other_arrays: Union["FancyArray", np.ndarray]) -> "FancyArray":
18
+
19
+ def concatenate(fancy_array: T, *other_arrays: Union[T, np.ndarray]) -> T:
18
20
  """Concatenate arrays."""
19
21
  np_arrays = [array if isinstance(array, np.ndarray) else array.data for array in other_arrays]
20
22
  try:
@@ -24,7 +26,7 @@ def concatenate(fancy_array: "FancyArray", *other_arrays: Union["FancyArray", np
24
26
  return fancy_array.__class__(data=concatenated)
25
27
 
26
28
 
27
- def unique(array: "FancyArray", **kwargs):
29
+ def unique(array: T, **kwargs):
28
30
  """Return the unique elements of the array."""
29
31
  for column in array.columns:
30
32
  if np.issubdtype(array.dtype[column], np.floating) and np.isnan(array[column]).any():
@@ -37,13 +39,13 @@ def unique(array: "FancyArray", **kwargs):
37
39
  return array.__class__(data=unique_data)
38
40
 
39
41
 
40
- def sort(array: "FancyArray", axis=-1, kind=None, order=None) -> "FancyArray":
42
+ def sort(array: T, axis=-1, kind=None, order=None) -> T:
41
43
  """Sort the array in-place and return sorted array."""
42
44
  array.data.sort(axis=axis, kind=kind, order=order)
43
45
  return array
44
46
 
45
47
 
46
- def array_equal(array1: "FancyArray", array2: "FancyArray", equal_nan: bool = True) -> bool:
48
+ def array_equal(array1: T, array2: T, equal_nan: bool = True) -> bool:
47
49
  """Return True if two arrays are equal."""
48
50
  if equal_nan:
49
51
  return array_equal_with_nan(array1.data, array2.data)
@@ -66,7 +66,7 @@ class FancyArray(ABC):
66
66
  self._data = data
67
67
 
68
68
  @property
69
- def data(self: Self):
69
+ def data(self: Self) -> NDArray:
70
70
  return self._data
71
71
 
72
72
  @classmethod
@@ -9,6 +9,7 @@ from typing import Literal
9
9
  import numpy as np
10
10
  from numpy.typing import NDArray
11
11
 
12
+ from power_grid_model_ds._core.fancypy import concatenate
12
13
  from power_grid_model_ds._core.model.arrays.base.array import FancyArray
13
14
  from power_grid_model_ds._core.model.dtypes.appliances import Source, SymGen, SymLoad
14
15
  from power_grid_model_ds._core.model.dtypes.branches import (
@@ -99,7 +100,26 @@ class TransformerArray(Transformer, BranchArray):
99
100
 
100
101
 
101
102
  class Branch3Array(IdArray, Branch3):
102
- pass
103
+ def as_branches(self) -> BranchArray:
104
+ """Convert Branch3Array to BranchArray."""
105
+ branches_1_2 = BranchArray.empty(self.size)
106
+ branches_1_2.from_node = self.node_1
107
+ branches_1_2.to_node = self.node_2
108
+ branches_1_2.from_status = self.status_1
109
+ branches_1_2.to_status = self.status_2
110
+
111
+ branches_1_3 = BranchArray.empty(self.size)
112
+ branches_1_3.from_node = self.node_1
113
+ branches_1_3.to_node = self.node_3
114
+ branches_1_3.from_status = self.status_1
115
+ branches_1_3.to_status = self.status_3
116
+
117
+ branches_2_3 = BranchArray.empty(self.size)
118
+ branches_2_3.from_node = self.node_2
119
+ branches_2_3.to_node = self.node_3
120
+ branches_2_3.from_status = self.status_2
121
+ branches_2_3.to_status = self.status_3
122
+ return concatenate(branches_1_2, branches_1_3, branches_2_3)
103
123
 
104
124
 
105
125
  class ThreeWindingTransformerArray(Branch3Array, ThreeWindingTransformer):
@@ -15,7 +15,6 @@ from power_grid_model_ds._core.model.graphs.errors import (
15
15
  MissingNodeError,
16
16
  NoPathBetweenNodes,
17
17
  )
18
- from power_grid_model_ds._core.model.utils import _get_branch3_branches
19
18
 
20
19
  if TYPE_CHECKING:
21
20
  from power_grid_model_ds._core.model.grids.base import Grid
@@ -175,8 +174,7 @@ class BaseGraphModel(ABC):
175
174
  def add_branch3_array(self, branch3_array: Branch3Array) -> None:
176
175
  """Add all branch3s in the branch3 array to the graph."""
177
176
  for branch3 in branch3_array:
178
- branches = _get_branch3_branches(branch3)
179
- self.add_branch_array(branches)
177
+ self.add_branch_array(branch3.as_branches())
180
178
 
181
179
  def delete_branch_array(self, branch_array: BranchArray, raise_on_fail: bool = True) -> None:
182
180
  """Delete all branches in branch_array from the graph."""
@@ -187,8 +185,7 @@ class BaseGraphModel(ABC):
187
185
  def delete_branch3_array(self, branch3_array: Branch3Array, raise_on_fail: bool = True) -> None:
188
186
  """Delete all branch3s in the branch3 array from the graph."""
189
187
  for branch3 in branch3_array:
190
- branches = _get_branch3_branches(branch3)
191
- self.delete_branch_array(branches, raise_on_fail=raise_on_fail)
188
+ self.delete_branch_array(branch3.as_branches(), raise_on_fail=raise_on_fail)
192
189
 
193
190
  @contextmanager
194
191
  def tmp_remove_nodes(self, nodes: list[int]) -> Generator:
@@ -8,12 +8,13 @@ from dash_bootstrap_components.icons import FONT_AWESOME
8
8
 
9
9
  from power_grid_model_ds._core.model.grids.base import Grid
10
10
  from power_grid_model_ds._core.visualizer.callbacks import ( # noqa: F401 # pylint: disable=unused-import
11
- element_scaling,
11
+ config,
12
12
  element_selection,
13
- layout_dropdown,
13
+ header,
14
14
  search_form,
15
15
  )
16
16
  from power_grid_model_ds._core.visualizer.layout.cytoscape_html import get_cytoscape_html
17
+ from power_grid_model_ds._core.visualizer.layout.cytoscape_styling import DEFAULT_STYLESHEET
17
18
  from power_grid_model_ds._core.visualizer.layout.header import HEADER_HTML
18
19
  from power_grid_model_ds._core.visualizer.layout.selection_output import SELECTION_OUTPUT_HTML
19
20
  from power_grid_model_ds._core.visualizer.parsers import parse_branches, parse_node_array
@@ -76,6 +77,7 @@ def get_app_layout(grid: Grid) -> html.Div:
76
77
  return html.Div(
77
78
  [
78
79
  columns_store,
80
+ dcc.Store(id="stylesheet-store", data=DEFAULT_STYLESHEET),
79
81
  HEADER_HTML,
80
82
  html.Hr(style={"border-color": "white", "margin": "0"}),
81
83
  cytoscape_html,
@@ -0,0 +1,66 @@
1
+ # SPDX-FileCopyrightText: Contributors to the Power Grid Model project <powergridmodel@lfenergy.org>
2
+ #
3
+ # SPDX-License-Identifier: MPL-2.0
4
+
5
+
6
+ from dash import Input, Output, State, callback
7
+ from dash.exceptions import PreventUpdate
8
+
9
+ from power_grid_model_ds._core.visualizer.layout.cytoscape_styling import BRANCH_WIDTH, NODE_SIZE
10
+ from power_grid_model_ds._core.visualizer.typing import STYLESHEET
11
+
12
+
13
+ @callback(
14
+ Output("stylesheet-store", "data", allow_duplicate=True),
15
+ Output("cytoscape-graph", "stylesheet", allow_duplicate=True),
16
+ Input("node-scale-input", "value"),
17
+ Input("edge-scale-input", "value"),
18
+ State("stylesheet-store", "data"),
19
+ prevent_initial_call=True,
20
+ )
21
+ def scale_elements(node_scale: float, edge_scale: float, stylesheet: STYLESHEET) -> tuple[STYLESHEET, STYLESHEET]:
22
+ """Callback to scale the elements of the graph."""
23
+ if stylesheet is None:
24
+ raise PreventUpdate
25
+ if node_scale == 1 and edge_scale == 1:
26
+ raise PreventUpdate
27
+ new_stylesheet = stylesheet.copy()
28
+ edge_style = {
29
+ "selector": "edge",
30
+ "style": {
31
+ "width": BRANCH_WIDTH * edge_scale,
32
+ },
33
+ }
34
+ new_stylesheet.append(edge_style)
35
+ node_style = {
36
+ "selector": "node",
37
+ "style": {
38
+ "height": NODE_SIZE * node_scale,
39
+ "width": NODE_SIZE * node_scale,
40
+ },
41
+ }
42
+ new_stylesheet.append(node_style)
43
+
44
+ return new_stylesheet, new_stylesheet
45
+
46
+
47
+ @callback(Output("cytoscape-graph", "layout"), Input("dropdown-update-layout", "value"), prevent_initial_call=True)
48
+ def update_layout(layout):
49
+ """Callback to update the layout of the graph."""
50
+ return {"name": layout, "animate": True}
51
+
52
+
53
+ @callback(
54
+ Output("cytoscape-graph", "stylesheet", allow_duplicate=True),
55
+ Input("show-arrows", "value"),
56
+ State("cytoscape-graph", "stylesheet"),
57
+ prevent_initial_call=True,
58
+ )
59
+ def update_arrows(show_arrows, current_stylesheet):
60
+ """Callback to update the arrow style of edges in the graph."""
61
+ selectors = [rule["selector"] for rule in current_stylesheet]
62
+ index = selectors.index("edge")
63
+ edge_style = current_stylesheet[index]["style"]
64
+
65
+ edge_style["target-arrow-shape"] = "triangle" if show_arrows else "none"
66
+ return current_stylesheet
@@ -0,0 +1,30 @@
1
+ # SPDX-FileCopyrightText: Contributors to the Power Grid Model project <powergridmodel@lfenergy.org>
2
+ #
3
+ # SPDX-License-Identifier: MPL-2.0
4
+
5
+ import dash
6
+ from dash import Input, Output, callback
7
+
8
+ from power_grid_model_ds._core.visualizer.layout.header import CONFIG_DIV, LEGENDA_DIV, SEARCH_DIV
9
+
10
+
11
+ @callback(
12
+ Output("header-right-col", "children"),
13
+ [
14
+ Input("btn-legend", "n_clicks"),
15
+ Input("btn-search", "n_clicks"),
16
+ Input("btn-config", "n_clicks"),
17
+ ],
18
+ )
19
+ def update_right_col(_btn1, _btn2, _btn3):
20
+ """Update the right column content based on the button clicked."""
21
+ ctx = dash.callback_context
22
+ if not ctx.triggered:
23
+ return LEGENDA_DIV
24
+ button_id = ctx.triggered[0]["prop_id"].split(".")[0]
25
+ button_map = {
26
+ "btn-legend": LEGENDA_DIV,
27
+ "btn-search": SEARCH_DIV,
28
+ "btn-config": CONFIG_DIV,
29
+ }
30
+ return button_map.get(button_id, "Right Column")
@@ -1,12 +1,12 @@
1
1
  # SPDX-FileCopyrightText: Contributors to the Power Grid Model project <powergridmodel@lfenergy.org>
2
2
  #
3
3
  # SPDX-License-Identifier: MPL-2.0
4
- from typing import Any
5
4
 
6
- from dash import Input, Output, callback
5
+ from dash import Input, Output, State, callback
6
+ from dash.exceptions import PreventUpdate
7
7
 
8
8
  from power_grid_model_ds._core.visualizer.layout.colors import CYTO_COLORS
9
- from power_grid_model_ds._core.visualizer.layout.cytoscape_styling import DEFAULT_STYLESHEET
9
+ from power_grid_model_ds._core.visualizer.typing import STYLESHEET
10
10
 
11
11
 
12
12
  @callback(
@@ -15,11 +15,12 @@ from power_grid_model_ds._core.visualizer.layout.cytoscape_styling import DEFAUL
15
15
  Input("search-form-column-input", "value"),
16
16
  Input("search-form-operator-input", "value"),
17
17
  Input("search-form-value-input", "value"),
18
+ State("stylesheet-store", "data"),
18
19
  )
19
- def search_element(group: str, column: str, operator: str, value: str) -> list[dict[str, Any]]:
20
+ def search_element(group: str, column: str, operator: str, value: str, stylesheet: STYLESHEET) -> STYLESHEET:
20
21
  """Color the specified element red based on the input values."""
21
22
  if not group or not column or not value:
22
- return DEFAULT_STYLESHEET
23
+ raise PreventUpdate
23
24
 
24
25
  # Determine if we're working with a node or an edge type
25
26
  if group == "node":
@@ -39,7 +40,8 @@ def search_element(group: str, column: str, operator: str, value: str) -> list[d
39
40
  "selector": selector,
40
41
  "style": style,
41
42
  }
42
- return DEFAULT_STYLESHEET + [new_style]
43
+ updated_stylesheet = stylesheet + [new_style]
44
+ return updated_stylesheet
43
45
 
44
46
 
45
47
  @callback(
@@ -10,8 +10,6 @@ from dash import html
10
10
  from power_grid_model_ds._core.visualizer.layout.colors import BACKGROUND_COLOR
11
11
  from power_grid_model_ds._core.visualizer.layout.cytoscape_styling import DEFAULT_STYLESHEET
12
12
 
13
- LAYOUT_OPTIONS = ["random", "circle", "concentric", "grid", "cose", "breadthfirst"]
14
-
15
13
  _CYTO_INNER_STYLE = {"width": "100%", "height": "100%", "background-color": BACKGROUND_COLOR}
16
14
  _CYTO_OUTER_STYLE = {"height": "80vh"}
17
15
 
@@ -3,29 +3,60 @@
3
3
  # SPDX-License-Identifier: MPL-2.0
4
4
 
5
5
  import dash_bootstrap_components as dbc
6
+ from dash import html
6
7
 
7
- from power_grid_model_ds._core.visualizer.layout.colors import BACKGROUND_COLOR
8
- from power_grid_model_ds._core.visualizer.layout.cytoscape_config import LAYOUT_DROPDOWN_HTML, SCALE_INPUTS
9
- from power_grid_model_ds._core.visualizer.layout.legenda import LEGENDA_HTML
10
- from power_grid_model_ds._core.visualizer.layout.search_form import SEARCH_FORM_HTML
11
-
12
- _SEARCH_FORM_CARD_STYLE = {
13
- "background-color": "#555555",
14
- "color": "white",
15
- "border-left": "1px solid white",
16
- "border-right": "1px solid white",
17
- "border-radius": 0,
8
+ from power_grid_model_ds._core.visualizer.layout.header_config import CONFIG_ELEMENTS
9
+ from power_grid_model_ds._core.visualizer.layout.header_legenda import LEGENDA_ELEMENTS, LEGENDA_STYLE
10
+ from power_grid_model_ds._core.visualizer.layout.header_search import SEARCH_ELEMENTS
11
+
12
+ _MENU_BUTTON_STYLE_CLASS = "me-2 btn-outline-primary"
13
+
14
+ _LEFT_COLUMN_HTML = dbc.Col(
15
+ [
16
+ dbc.Button("Legend", id="btn-legend", className=_MENU_BUTTON_STYLE_CLASS),
17
+ dbc.Button("Search", id="btn-search", className=_MENU_BUTTON_STYLE_CLASS),
18
+ dbc.Button("Config", id="btn-config", className=_MENU_BUTTON_STYLE_CLASS),
19
+ ],
20
+ id="header-left-col",
21
+ width=5,
22
+ style={
23
+ "display": "flex",
24
+ "align-items": "center",
25
+ "justify-content": "center",
26
+ "border-right": "1px solid white",
27
+ },
28
+ )
29
+
30
+
31
+ _RIGHT_COLUMN_STYLE = {
32
+ "display": "flex",
33
+ "align-items": "center",
34
+ "width": "100%",
18
35
  }
19
36
 
20
37
 
38
+ CONFIG_DIV = html.Div(CONFIG_ELEMENTS, style=_RIGHT_COLUMN_STYLE | {"justify-content": "space-between"})
39
+ SEARCH_DIV = html.Div(SEARCH_ELEMENTS, style=_RIGHT_COLUMN_STYLE | {"justify-content": "center"})
40
+ LEGENDA_DIV = html.Div(LEGENDA_ELEMENTS, style=_RIGHT_COLUMN_STYLE | LEGENDA_STYLE)
41
+
42
+ _RIGHT_COLUMN_HTML = dbc.Col(
43
+ [LEGENDA_DIV, SEARCH_DIV, CONFIG_DIV],
44
+ id="header-right-col",
45
+ width=7,
46
+ )
47
+
21
48
  HEADER_HTML = dbc.Row(
22
49
  [
23
- dbc.Col(LEGENDA_HTML, className="d-flex align-items-center"),
24
- dbc.Col(
25
- dbc.Card(SEARCH_FORM_HTML, style=_SEARCH_FORM_CARD_STYLE),
26
- className="d-flex justify-content-center align-items-center",
27
- ),
28
- dbc.Col(SCALE_INPUTS + LAYOUT_DROPDOWN_HTML, className="d-flex justify-content-end align-items-center"),
50
+ _LEFT_COLUMN_HTML,
51
+ _RIGHT_COLUMN_HTML,
29
52
  ],
30
- style={"background-color": BACKGROUND_COLOR},
53
+ style={
54
+ "background-color": "#343a40",
55
+ "color": "white",
56
+ "padding": "1rem 0",
57
+ "margin": 0,
58
+ "height": "90px",
59
+ "width": "100%",
60
+ },
61
+ align="center",
31
62
  )
@@ -0,0 +1,71 @@
1
+ # SPDX-FileCopyrightText: Contributors to the Power Grid Model project <powergridmodel@lfenergy.org>
2
+ #
3
+ # SPDX-License-Identifier: MPL-2.0
4
+ from enum import Enum
5
+
6
+ import dash_bootstrap_components as dbc
7
+ from dash import dcc, html
8
+
9
+ from power_grid_model_ds._core.visualizer.layout.colors import CYTO_COLORS
10
+
11
+ NODE_SCALE_HTML = [
12
+ html.I(className="fas fa-circle", style={"color": CYTO_COLORS["node"], "margin-right": "10px"}),
13
+ dcc.Input(
14
+ id="node-scale-input",
15
+ type="number",
16
+ value=1,
17
+ min=0.1,
18
+ step=0.1,
19
+ style={"width": "75px"},
20
+ ),
21
+ html.Span(style={"margin-right": "10px"}),
22
+ ]
23
+
24
+ EDGE_SCALE_HTML = [
25
+ html.I(className="fas fa-arrow-right-long", style={"color": CYTO_COLORS["line"], "margin-right": "10px"}),
26
+ dcc.Input(
27
+ id="edge-scale-input",
28
+ type="number",
29
+ value=1,
30
+ min=0.1,
31
+ step=0.1,
32
+ style={"width": "75px"},
33
+ ),
34
+ ]
35
+
36
+ _SCALING_DIV = html.Div(NODE_SCALE_HTML + EDGE_SCALE_HTML, style={"margin": "0 20px 0 10px"})
37
+
38
+
39
+ class LayoutOptions(Enum):
40
+ """Cytoscape layout options."""
41
+
42
+ RANDOM = "random"
43
+ CIRCLE = "circle"
44
+ CONCENTRIC = "concentric"
45
+ GRID = "grid"
46
+ COSE = "cose"
47
+ BREADTHFIRST = "breadthfirst"
48
+
49
+
50
+ _LAYOUT_DROPDOWN = html.Div(
51
+ dcc.Dropdown(
52
+ id="dropdown-update-layout",
53
+ placeholder="Select layout",
54
+ value=LayoutOptions.BREADTHFIRST.value,
55
+ clearable=False,
56
+ options=[{"label": option.value, "value": option.value} for option in LayoutOptions],
57
+ style={"width": "200px"},
58
+ ),
59
+ style={"margin": "0 20px 0 10px", "color": "black"},
60
+ )
61
+
62
+
63
+ _ARROWS_CHECKBOX = dbc.Checkbox(
64
+ id="show-arrows",
65
+ label="Show arrows",
66
+ value=True,
67
+ label_style={"color": "white"},
68
+ style={"margin-top": "10px"},
69
+ )
70
+
71
+ CONFIG_ELEMENTS = [_LAYOUT_DROPDOWN, _ARROWS_CHECKBOX, _SCALING_DIV]
@@ -0,0 +1,36 @@
1
+ # SPDX-FileCopyrightText: Contributors to the Power Grid Model project <powergridmodel@lfenergy.org>
2
+ #
3
+ # SPDX-License-Identifier: MPL-2.0
4
+
5
+ import dash_bootstrap_components as dbc
6
+ from dash import html
7
+
8
+ from power_grid_model_ds._core.visualizer.layout.colors import CYTO_COLORS
9
+
10
+ _BOOTSTRAP_ARROW_ICON_CLASS = "fas fa-arrow-right-long"
11
+ _MARGIN = "0 10px"
12
+
13
+ LEGENDA_STYLE = {"margin": _MARGIN, "text-shadow": "0 0 5px #000", "justify-content": "center"}
14
+
15
+ _FONT_SIZE = "2.5em"
16
+
17
+ NODE_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["node"]}
18
+ _SUBSTATION_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["substation_node"]}
19
+ _LINE_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["line"]}
20
+ _LINK_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["link"]}
21
+ _TRANSFORMER_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["transformer"]}
22
+ _OPEN_BRANCH_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["open_branch"]}
23
+ LEGENDA_ELEMENTS = [
24
+ html.I(className="fas fa-circle", id="node-icon", style=NODE_ICON_STYLE),
25
+ dbc.Tooltip("Node", target="node-icon", placement="bottom"),
26
+ html.I(className="fas fa-diamond", id="substation-icon", style=_SUBSTATION_ICON_STYLE),
27
+ dbc.Tooltip("Substation", target="substation-icon", placement="bottom"),
28
+ html.I(className=_BOOTSTRAP_ARROW_ICON_CLASS, id="line-icon", style=_LINE_ICON_STYLE),
29
+ dbc.Tooltip("Line", target="line-icon", placement="bottom"),
30
+ html.I(className=_BOOTSTRAP_ARROW_ICON_CLASS, id="transformer-icon", style=_TRANSFORMER_ICON_STYLE),
31
+ dbc.Tooltip("Transformer", target="transformer-icon", placement="bottom"),
32
+ html.I(className=_BOOTSTRAP_ARROW_ICON_CLASS, id="link-icon", style=_LINK_ICON_STYLE),
33
+ dbc.Tooltip("Link", target="link-icon", placement="bottom"),
34
+ html.I(className="fas fa-ellipsis", id="open-branch-icon", style=_OPEN_BRANCH_ICON_STYLE),
35
+ dbc.Tooltip("Open Branch", target="open-branch-icon", placement="bottom"),
36
+ ]
@@ -44,21 +44,15 @@ OPERATOR_INPUT = dbc.Select(
44
44
 
45
45
 
46
46
  # Arrange as a sentence
47
- SEARCH_FORM_HTML = html.Div(
48
- [
49
- html.Span("Search ", style=SPAN_TEXT_STYLE),
50
- GROUP_INPUT,
51
- html.Span(" with ", className="mx-2", style=SPAN_TEXT_STYLE),
52
- COLUMN_INPUT,
53
- OPERATOR_INPUT,
54
- VALUE_INPUT,
55
- ],
56
- style={
57
- "display": "flex",
58
- "align-items": "center",
59
- "justify-content": "center", # Centers items horizontally
60
- "padding": "10px",
61
- "margin": "0 auto", # Centers the container itself
62
- "width": "100%", # Ensures the container takes full width
63
- },
64
- )
47
+ SEARCH_ELEMENTS = [
48
+ html.Div(
49
+ [
50
+ html.Span("Search ", style=SPAN_TEXT_STYLE),
51
+ GROUP_INPUT,
52
+ html.Span(" with ", style=SPAN_TEXT_STYLE),
53
+ COLUMN_INPUT,
54
+ OPERATOR_INPUT,
55
+ VALUE_INPUT,
56
+ ]
57
+ )
58
+ ]
@@ -6,7 +6,6 @@ from typing import Any, Literal
6
6
 
7
7
  from power_grid_model_ds._core.model.arrays.base.array import FancyArray
8
8
  from power_grid_model_ds._core.model.grids.base import Grid
9
- from power_grid_model_ds._core.model.utils import _get_branch3_branches
10
9
  from power_grid_model_ds.arrays import Branch3Array, BranchArray, NodeArray
11
10
 
12
11
 
@@ -41,15 +40,15 @@ def parse_branch3_array(branches: Branch3Array, group: Literal["transformer"]) -
41
40
  """Parse the three-winding transformer array."""
42
41
  parsed_branches = []
43
42
  columns = branches.columns
44
- for branch in branches:
45
- for branch_ in _get_branch3_branches(branch):
46
- cyto_elements = {"data": _array_to_dict(branch_, columns)}
43
+ for branch3 in branches:
44
+ for branch1 in branch3.as_branches():
45
+ cyto_elements = {"data": _array_to_dict(branch1, columns)}
47
46
  cyto_elements["data"].update(
48
47
  {
49
48
  # IDs need to be unique, so we combine the branch ID with the from and to nodes
50
- "id": str(branch.id.item()) + f"_{branch_.from_node.item()}_{branch_.to_node.item()}",
51
- "source": str(branch_.from_node.item()),
52
- "target": str(branch_.to_node.item()),
49
+ "id": str(branch3.id.item()) + f"_{branch1.from_node.item()}_{branch1.to_node.item()}",
50
+ "source": str(branch1.from_node.item()),
51
+ "target": str(branch1.to_node.item()),
53
52
  "group": group,
54
53
  }
55
54
  )
@@ -0,0 +1,7 @@
1
+ # SPDX-FileCopyrightText: Contributors to the Power Grid Model project <powergridmodel@lfenergy.org>
2
+ #
3
+ # SPDX-License-Identifier: MPL-2.0
4
+
5
+ from typing import Any
6
+
7
+ STYLESHEET = list[dict[str, Any]]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: power-grid-model-ds
3
- Version: 1.4.2
3
+ Version: 1.4.4
4
4
  Summary: Power Grid Model extension which provides a grid data structure for simulation and analysis
5
5
  Author-email: Contributors to the Power Grid Model project <powergridmodel@lfenergy.org>
6
6
  License: MPL-2.0
@@ -36,7 +36,7 @@ Requires-Dist: isort>=5.13.2; extra == "dev"
36
36
  Requires-Dist: mypy>=1.9.0; extra == "dev"
37
37
  Requires-Dist: pre-commit>=4; extra == "dev"
38
38
  Requires-Dist: dash>=3.0.0; extra == "dev"
39
- Requires-Dist: dash-bootstrap-components>=2.0.0; extra == "dev"
39
+ Requires-Dist: dash-bootstrap-components>=2.0.3; extra == "dev"
40
40
  Requires-Dist: dash-cytoscape>=1.0.2; extra == "dev"
41
41
  Provides-Extra: visualizer
42
42
  Requires-Dist: dash>=3.0.0; extra == "visualizer"
@@ -8,7 +8,7 @@ power_grid_model_ds/generators.py,sha256=suQCHIzLOXjJj3tLn1-vuzR9m6V-bhFZQWEukTp
8
8
  power_grid_model_ds/graph_models.py,sha256=so5niaXJqtuL0hUmtSPxV6Bven5c8DfAlF3MM4I1d28,348
9
9
  power_grid_model_ds/visualizer.py,sha256=W9GfWuM-CrDTnniCj1y-lxSt6IQkLJViW5aPC4syauw,411
10
10
  power_grid_model_ds/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- power_grid_model_ds/_core/fancypy.py,sha256=EKH1gIACBPF9lUFI4kUPZJ_peS6B_udsLTs-PysdIns,2065
11
+ power_grid_model_ds/_core/fancypy.py,sha256=9Prli1dCJTTZdVVekQWgQPb4TbA_iMK0PzWTg_Do9EM,2024
12
12
  power_grid_model_ds/_core/load_flow.py,sha256=B5HKMa87OrzTcOteN-RLGzsj5XrTiw7lhpXfqPj6yys,6304
13
13
  power_grid_model_ds/_core/data_source/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  power_grid_model_ds/_core/data_source/generator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -21,16 +21,15 @@ power_grid_model_ds/_core/data_source/generator/arrays/source.py,sha256=rlrjDI73
21
21
  power_grid_model_ds/_core/data_source/generator/arrays/transformer.py,sha256=o2MOhWfitED2YDACLrxSYbeyDf3Rr_4fF0rsW2nROD4,1526
22
22
  power_grid_model_ds/_core/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  power_grid_model_ds/_core/model/constants.py,sha256=pxkZ-a4J8RVu4ziw_A6usY81I2tt6sOY1xDBsv6Ta14,746
24
- power_grid_model_ds/_core/model/utils.py,sha256=j9DDnwTMIbkWTu7HdxGvrRKVZZPaIFtZN212ujsD7p0,786
25
24
  power_grid_model_ds/_core/model/arrays/__init__.py,sha256=WMMIUW5RAkJ6E7tRtu8sImhxjnQDo7h5J2I9dhvfAcw,1013
26
- power_grid_model_ds/_core/model/arrays/pgm_arrays.py,sha256=Vmzj6BFVY3vZqfpiOZ0-KDNdi3EbkWv3cUHUx8D29jw,3318
25
+ power_grid_model_ds/_core/model/arrays/pgm_arrays.py,sha256=9IxP7RQOCRCBZeeC65myLBJVXx3mDayaC8fg9nzNMBk,4239
27
26
  power_grid_model_ds/_core/model/arrays/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
27
  power_grid_model_ds/_core/model/arrays/base/_build.py,sha256=NAdmzkjpC4lP-z1y0au8ZDuL7rWSwN-YG2VUv0u5lYM,6365
29
28
  power_grid_model_ds/_core/model/arrays/base/_filters.py,sha256=68DBuliTADfp2VNKpuTSq18fgPa5XC4MkxQIH6G9mV8,4241
30
29
  power_grid_model_ds/_core/model/arrays/base/_modify.py,sha256=TP8LojFMcZnyzhmshzNQnjlEVSZjE_xJ6BNQ4SpIBvA,2476
31
30
  power_grid_model_ds/_core/model/arrays/base/_optional.py,sha256=zEEaE5z7bjLiARb8WTYsgZhbtJYAT6BTd61IUdv_YTA,288
32
31
  power_grid_model_ds/_core/model/arrays/base/_string.py,sha256=H66DBYq8RHQHj6Gfn2tdEXKoL3ND64iVkZCt-Fwjdn0,3568
33
- power_grid_model_ds/_core/model/arrays/base/array.py,sha256=4PyIoKF4hrKbrBSy6167glg0qI1ZtXheuj11rGZHb8s,13156
32
+ power_grid_model_ds/_core/model/arrays/base/array.py,sha256=b6e8LBajvzYCfvTvADudG8lE9SnOdke769YFewOjnhs,13167
34
33
  power_grid_model_ds/_core/model/arrays/base/errors.py,sha256=M62aA2pv9AlSJSvniU1IJTtRC0jvBlMYRxv2SchTdDA,475
35
34
  power_grid_model_ds/_core/model/containers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
35
  power_grid_model_ds/_core/model/containers/base.py,sha256=O-GoE2oN-WJl5wKXCl3fUHbvW5qc0oZ2-oY-zUWBGbs,9037
@@ -48,7 +47,7 @@ power_grid_model_ds/_core/model/graphs/container.py,sha256=M10tTUF_Mn3d2xPmfW2UA
48
47
  power_grid_model_ds/_core/model/graphs/errors.py,sha256=-9fAsCqpKM0-lCM-tO2fVot9hqZBJa8WCxxqWEH_z6k,479
49
48
  power_grid_model_ds/_core/model/graphs/models/__init__.py,sha256=xwhMajQKIAfL1R3cq2sMNXMWtqfI5WGBi6-P4clyTes,262
50
49
  power_grid_model_ds/_core/model/graphs/models/_rustworkx_search.py,sha256=TqRR22TPx8XjRLukQxK8R8FjZvJ60CttDFctbISSbOM,2979
51
- power_grid_model_ds/_core/model/graphs/models/base.py,sha256=LTWn5QROenDxEOu_8d1ehFGg8rj7oCgxsnHX-JoEkEg,16822
50
+ power_grid_model_ds/_core/model/graphs/models/base.py,sha256=B1My17h5VPf9jrs4WbxMAowUKf4mKNdrkfyOf28P-Y8,16668
52
51
  power_grid_model_ds/_core/model/graphs/models/rustworkx.py,sha256=jccM7MUhNqH2215mk_X8ihQ-Q8IkjjRhUk4jSruaxy8,6158
53
52
  power_grid_model_ds/_core/model/grids/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
53
  power_grid_model_ds/_core/model/grids/_text_sources.py,sha256=3CWn0zjaUkFhrnSEIqAas52xeW0EX3EWXIXyo8XSQgw,4229
@@ -59,24 +58,25 @@ power_grid_model_ds/_core/utils/misc.py,sha256=fPjpczUr3IZ7EnAYI2darLzN2O8NJwhxg
59
58
  power_grid_model_ds/_core/utils/pickle.py,sha256=LGeTc7nu9RY1noOzLJzYaSHSWIgqzHy2xhmueKGuipc,1445
60
59
  power_grid_model_ds/_core/utils/zip.py,sha256=9RtJYhjlgNZOtxr4iI-CpsjT1axw5kCCqprfTjaIsiI,2197
61
60
  power_grid_model_ds/_core/visualizer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
- power_grid_model_ds/_core/visualizer/app.py,sha256=dnigMtdGkYquBpFDznLDogTzXR-BHPaa_scdF4GxUlw,3421
63
- power_grid_model_ds/_core/visualizer/parsers.py,sha256=2QBUkUQD4EsrcJKAY-G0q657ngU41ceMbBBd_0GKJvQ,3246
61
+ power_grid_model_ds/_core/visualizer/app.py,sha256=Syu8niHt1jTGrBOCexn5bsX6sZq0sHTFcI1bFo2Bjyk,3567
62
+ power_grid_model_ds/_core/visualizer/parsers.py,sha256=IYvnlunzZG-hqEjbVQGnDaZ37tLiYh5EEO39njyVjws,3168
63
+ power_grid_model_ds/_core/visualizer/typing.py,sha256=3q9AU7Uz0Cp06biIWLFw3zzmfsVSu8rPEFKkIQpHr-g,197
64
64
  power_grid_model_ds/_core/visualizer/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
- power_grid_model_ds/_core/visualizer/callbacks/element_scaling.py,sha256=l8PPSqglytqBQgZ4yyNVx3wMYLF8Fcx8ku4skbGNZLM,1136
65
+ power_grid_model_ds/_core/visualizer/callbacks/config.py,sha256=c1j30Q-dKYEKNf1fZVLcZWZ9o384k_okwfTfegQ5x8I,2268
66
66
  power_grid_model_ds/_core/visualizer/callbacks/element_selection.py,sha256=Teaeq0atd2rD_edaW0u_N-YCnaf6MQyC8WsgnEhQczk,963
67
- power_grid_model_ds/_core/visualizer/callbacks/layout_dropdown.py,sha256=ekO2imgbMrV_R8HpCicbOSjFO2m1tjsj-zF4RHih5RA,424
68
- power_grid_model_ds/_core/visualizer/callbacks/search_form.py,sha256=fi6azBaKIgV63vLCp0wrIB5mZ3zSWn2Jhc5VdR-Om44,2098
67
+ power_grid_model_ds/_core/visualizer/callbacks/header.py,sha256=dQnUNzKonMPcSpSaikIGrsM9OdZV_C2RdFuPigTVZzg,925
68
+ power_grid_model_ds/_core/visualizer/callbacks/search_form.py,sha256=KceSRKYcSAxUdfyfQ3MFbkb0GHljiWEnSk60ufjFoXg,2181
69
69
  power_grid_model_ds/_core/visualizer/layout/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
70
  power_grid_model_ds/_core/visualizer/layout/colors.py,sha256=tt-2LvkClYvQ5ozL2UCX5q63AbXaXXo7kK2yLAzeCVw,455
71
- power_grid_model_ds/_core/visualizer/layout/cytoscape_config.py,sha256=_vnncYWIRERIgwqJY8aBXUYoXYh3l6Vd6G4voN3kTVQ,1471
72
- power_grid_model_ds/_core/visualizer/layout/cytoscape_html.py,sha256=apiU1oOSrT30c2bYADUNNOGcAkG4rkqV5UtSLVWFMfU,1009
71
+ power_grid_model_ds/_core/visualizer/layout/cytoscape_html.py,sha256=EL6Z2ewCZc86NvoDQoek7MmZH_trPtRWXBcH1kfnR2Y,924
73
72
  power_grid_model_ds/_core/visualizer/layout/cytoscape_styling.py,sha256=o5Rh8uNCyt9YxODkNH76sx_wKs8aCBrCMVGCFBTtegQ,3288
74
- power_grid_model_ds/_core/visualizer/layout/header.py,sha256=el-5SlWIPeEbZZLbi3vYz9CjanTlhuChVfqkktLCHjw,1165
75
- power_grid_model_ds/_core/visualizer/layout/legenda.py,sha256=8JTrMRgaYRaSIXAEoM0b3PgX7AYvW0_fHuYg8nY4y0g,2161
76
- power_grid_model_ds/_core/visualizer/layout/search_form.py,sha256=4LPU6MjD3QEIeBEOOWBvV5-GyLMqNYWyKcUa_oWScCs,2002
73
+ power_grid_model_ds/_core/visualizer/layout/header.py,sha256=PdIXUBZgdacTc7V99tR93SFcMjUHAzWdFGVGjq7PhMw,1829
74
+ power_grid_model_ds/_core/visualizer/layout/header_config.py,sha256=e0W7tgbDTu-dJ4YDZ89vGCiQr5G12Fypr1popFyitgs,1866
75
+ power_grid_model_ds/_core/visualizer/layout/header_legenda.py,sha256=tmSIxQFW0d4ey64J_w9QwcZji3EIg7BZ7Rf8w167xb8,2086
76
+ power_grid_model_ds/_core/visualizer/layout/header_search.py,sha256=RYTQosQaAeKyOiPNR9c0ofMiY2wKmmJCPENmlkv6BZw,1726
77
77
  power_grid_model_ds/_core/visualizer/layout/selection_output.py,sha256=fuPAdG5XmTj2E0oQ8w_tp9PGbB8bJ5fguteLtnM1EDg,534
78
- power_grid_model_ds-1.4.2.dist-info/licenses/LICENSE,sha256=GpbnG1pNl-ORtSP6dmHeiZvwy36UFli6MEZy1XlmBqo,14906
79
- power_grid_model_ds-1.4.2.dist-info/METADATA,sha256=GkP-FjhBko-W7soqRG_u2V4h3qq-g8difaeQG7qeSXY,8873
80
- power_grid_model_ds-1.4.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
81
- power_grid_model_ds-1.4.2.dist-info/top_level.txt,sha256=nJa103Eqvm5TESYEKPFVImfLg_ugGOBznikrM-rZQZg,20
82
- power_grid_model_ds-1.4.2.dist-info/RECORD,,
78
+ power_grid_model_ds-1.4.4.dist-info/licenses/LICENSE,sha256=GpbnG1pNl-ORtSP6dmHeiZvwy36UFli6MEZy1XlmBqo,14906
79
+ power_grid_model_ds-1.4.4.dist-info/METADATA,sha256=q3vceCLNnZdBWfbQBGzeK40hyjw7OjERqjzuqEXtTEQ,8873
80
+ power_grid_model_ds-1.4.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
81
+ power_grid_model_ds-1.4.4.dist-info/top_level.txt,sha256=nJa103Eqvm5TESYEKPFVImfLg_ugGOBznikrM-rZQZg,20
82
+ power_grid_model_ds-1.4.4.dist-info/RECORD,,
@@ -1,22 +0,0 @@
1
- # SPDX-FileCopyrightText: Contributors to the Power Grid Model project <powergridmodel@lfenergy.org>
2
- #
3
- # SPDX-License-Identifier: MPL-2.0
4
- from power_grid_model_ds._core.model.arrays.pgm_arrays import Branch3Array, BranchArray
5
-
6
-
7
- def _get_branch3_branches(branch3: Branch3Array) -> BranchArray:
8
- node_1 = branch3.node_1.item()
9
- node_2 = branch3.node_2.item()
10
- node_3 = branch3.node_3.item()
11
-
12
- status_1 = branch3.status_1.item()
13
- status_2 = branch3.status_2.item()
14
- status_3 = branch3.status_3.item()
15
-
16
- branches = BranchArray.zeros(3)
17
- branches.from_node = [node_1, node_1, node_2]
18
- branches.to_node = [node_2, node_3, node_3]
19
- branches.from_status = [status_1, status_1, status_2]
20
- branches.to_status = [status_2, status_3, status_3]
21
-
22
- return branches
@@ -1,37 +0,0 @@
1
- # SPDX-FileCopyrightText: Contributors to the Power Grid Model project <powergridmodel@lfenergy.org>
2
- #
3
- # SPDX-License-Identifier: MPL-2.0
4
-
5
- from copy import deepcopy
6
- from typing import Any
7
-
8
- from dash import Input, Output, callback
9
-
10
- from power_grid_model_ds._core.visualizer.layout.cytoscape_styling import BRANCH_WIDTH, DEFAULT_STYLESHEET, NODE_SIZE
11
-
12
-
13
- @callback(
14
- Output("cytoscape-graph", "stylesheet", allow_duplicate=True),
15
- Input("node-scale-input", "value"),
16
- Input("edge-scale-input", "value"),
17
- prevent_initial_call=True,
18
- )
19
- def scale_elements(node_scale: float, edge_scale: float) -> list[dict[str, Any]]:
20
- """Callback to scale the elements of the graph."""
21
- new_stylesheet = deepcopy(DEFAULT_STYLESHEET)
22
- edge_style = {
23
- "selector": "edge",
24
- "style": {
25
- "width": BRANCH_WIDTH * edge_scale,
26
- },
27
- }
28
- new_stylesheet.append(edge_style)
29
- node_style = {
30
- "selector": "node",
31
- "style": {
32
- "height": NODE_SIZE * node_scale,
33
- "width": NODE_SIZE * node_scale,
34
- },
35
- }
36
- new_stylesheet.append(node_style)
37
- return new_stylesheet
@@ -1,11 +0,0 @@
1
- # SPDX-FileCopyrightText: Contributors to the Power Grid Model project <powergridmodel@lfenergy.org>
2
- #
3
- # SPDX-License-Identifier: MPL-2.0
4
-
5
- from dash import Input, Output, callback
6
-
7
-
8
- @callback(Output("cytoscape-graph", "layout"), Input("dropdown-update-layout", "value"), prevent_initial_call=True)
9
- def update_layout(layout):
10
- """Callback to update the layout of the graph."""
11
- return {"name": layout, "animate": True}
@@ -1,54 +0,0 @@
1
- # SPDX-FileCopyrightText: Contributors to the Power Grid Model project <powergridmodel@lfenergy.org>
2
- #
3
- # SPDX-License-Identifier: MPL-2.0
4
-
5
- from dash import dcc, html
6
-
7
- from power_grid_model_ds._core.visualizer.layout.colors import CYTO_COLORS
8
- from power_grid_model_ds._core.visualizer.layout.cytoscape_html import LAYOUT_OPTIONS
9
-
10
- NODE_SCALE_HTML = [
11
- html.I(className="fas fa-circle", style={"color": CYTO_COLORS["node"], "margin-right": "10px"}),
12
- dcc.Input(
13
- id="node-scale-input",
14
- type="number",
15
- value=1,
16
- min=0.1,
17
- step=0.1,
18
- style={"width": "75px"},
19
- ),
20
- html.Span(style={"margin-right": "10px"}),
21
- ]
22
-
23
- EDGE_SCALE_HTML = [
24
- html.I(className="fas fa-arrow-right-long", style={"color": CYTO_COLORS["line"], "margin-right": "10px"}),
25
- dcc.Input(
26
- id="edge-scale-input",
27
- type="number",
28
- value=1,
29
- min=0.1,
30
- step=0.1,
31
- style={"width": "75px"},
32
- ),
33
- ]
34
-
35
- SCALE_INPUTS = [
36
- html.Div(
37
- NODE_SCALE_HTML + EDGE_SCALE_HTML,
38
- style={"margin": "0 20px 0 10px"},
39
- ),
40
- ]
41
-
42
- LAYOUT_DROPDOWN_HTML = [
43
- html.Div(
44
- dcc.Dropdown(
45
- id="dropdown-update-layout",
46
- placeholder="Select layout",
47
- value="",
48
- clearable=False,
49
- options=[{"label": name.capitalize(), "value": name} for name in LAYOUT_OPTIONS],
50
- style={"width": "200px"},
51
- ),
52
- style={"margin": "0 20px 0 10px"},
53
- )
54
- ]
@@ -1,41 +0,0 @@
1
- # SPDX-FileCopyrightText: Contributors to the Power Grid Model project <powergridmodel@lfenergy.org>
2
- #
3
- # SPDX-License-Identifier: MPL-2.0
4
-
5
- import dash_bootstrap_components as dbc
6
- from dash import html
7
-
8
- from power_grid_model_ds._core.visualizer.layout.colors import CYTO_COLORS
9
-
10
- _MARGIN = "0 10px"
11
- _FONT_SIZE = "2.5em"
12
-
13
- NODE_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["node"]}
14
- _SUBSTATION_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["substation_node"]}
15
- _LINE_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["line"]}
16
- _LINK_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["link"]}
17
- _TRANSFORMER_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["transformer"]}
18
- _OPEN_BRANCH_ICON_STYLE = {"font-size": _FONT_SIZE, "margin": _MARGIN, "color": CYTO_COLORS["open_branch"]}
19
- LEGENDA_HTML = html.Div(
20
- [
21
- html.I(className="fas fa-circle", id="node-icon", style=NODE_ICON_STYLE),
22
- dbc.Tooltip("Node", target="node-icon", placement="bottom"),
23
- html.I(className="fas fa-diamond", id="substation-icon", style=_SUBSTATION_ICON_STYLE),
24
- dbc.Tooltip("Substation", target="substation-icon", placement="bottom"),
25
- html.I(className="fas fa-arrow-right-long", id="line-icon", style=_LINE_ICON_STYLE),
26
- dbc.Tooltip("Line", target="line-icon", placement="bottom"),
27
- html.I(className="fas fa-arrow-right-long", id="transformer-icon", style=_TRANSFORMER_ICON_STYLE),
28
- dbc.Tooltip("Transformer", target="transformer-icon", placement="bottom"),
29
- html.I(className="fas fa-arrow-right-long", id="link-icon", style=_LINK_ICON_STYLE),
30
- dbc.Tooltip("Link", target="link-icon", placement="bottom"),
31
- html.I(className="fas fa-ellipsis", id="open-branch-icon", style=_OPEN_BRANCH_ICON_STYLE),
32
- dbc.Tooltip("Open Branch", target="open-branch-icon", placement="bottom"),
33
- ],
34
- style={
35
- "display": "flex",
36
- "align-items": "center",
37
- "margin": _MARGIN,
38
- "width": "100%",
39
- "text-shadow": "0 0 5px #000",
40
- },
41
- )