flixopt 2.1.7__py3-none-any.whl → 2.1.8__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.
Potentially problematic release.
This version of flixopt might be problematic. Click here for more details.
- docs/user-guide/Mathematical Notation/Effects, Penalty & Objective.md +8 -8
- docs/user-guide/Mathematical Notation/Flow.md +3 -3
- docs/user-guide/Mathematical Notation/InvestParameters.md +3 -0
- docs/user-guide/Mathematical Notation/LinearConverter.md +3 -3
- docs/user-guide/Mathematical Notation/OnOffParameters.md +3 -0
- docs/user-guide/Mathematical Notation/Storage.md +1 -1
- flixopt/aggregation.py +33 -32
- flixopt/calculation.py +158 -58
- flixopt/components.py +673 -150
- flixopt/config.py +17 -8
- flixopt/core.py +59 -54
- flixopt/effects.py +144 -63
- flixopt/elements.py +292 -107
- flixopt/features.py +61 -58
- flixopt/flow_system.py +69 -48
- flixopt/interface.py +952 -113
- flixopt/io.py +15 -10
- flixopt/linear_converters.py +373 -81
- flixopt/network_app.py +75 -39
- flixopt/plotting.py +215 -87
- flixopt/results.py +382 -209
- flixopt/solvers.py +25 -21
- flixopt/structure.py +41 -37
- flixopt/utils.py +10 -7
- {flixopt-2.1.7.dist-info → flixopt-2.1.8.dist-info}/METADATA +46 -42
- {flixopt-2.1.7.dist-info → flixopt-2.1.8.dist-info}/RECORD +30 -28
- scripts/gen_ref_pages.py +1 -1
- {flixopt-2.1.7.dist-info → flixopt-2.1.8.dist-info}/WHEEL +0 -0
- {flixopt-2.1.7.dist-info → flixopt-2.1.8.dist-info}/licenses/LICENSE +0 -0
- {flixopt-2.1.7.dist-info → flixopt-2.1.8.dist-info}/top_level.txt +0 -0
flixopt/network_app.py
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
2
3
|
import logging
|
|
3
4
|
import socket
|
|
4
5
|
import threading
|
|
5
|
-
from typing import
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
6
7
|
|
|
7
8
|
try:
|
|
8
9
|
import dash_cytoscape as cyto
|
|
9
10
|
import dash_daq as daq
|
|
10
|
-
import networkx
|
|
11
|
+
import networkx as nx
|
|
11
12
|
from dash import Dash, Input, Output, State, callback_context, dcc, html, no_update
|
|
12
13
|
from werkzeug.serving import make_server
|
|
13
14
|
|
|
@@ -17,9 +18,13 @@ except ImportError as e:
|
|
|
17
18
|
DASH_CYTOSCAPE_AVAILABLE = False
|
|
18
19
|
VISUALIZATION_ERROR = str(e)
|
|
19
20
|
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from .flow_system import FlowSystem
|
|
23
|
+
|
|
24
|
+
import networkx as nx
|
|
25
|
+
|
|
20
26
|
from .components import LinearConverter, Sink, Source, SourceAndSink, Storage
|
|
21
|
-
from .elements import Bus
|
|
22
|
-
from .flow_system import FlowSystem
|
|
27
|
+
from .elements import Bus
|
|
23
28
|
|
|
24
29
|
logger = logging.getLogger('flixopt')
|
|
25
30
|
|
|
@@ -110,8 +115,16 @@ class VisualizationConfig:
|
|
|
110
115
|
]
|
|
111
116
|
|
|
112
117
|
|
|
113
|
-
def flow_graph(flow_system: FlowSystem) ->
|
|
118
|
+
def flow_graph(flow_system: FlowSystem) -> nx.DiGraph:
|
|
114
119
|
"""Convert FlowSystem to NetworkX graph - simplified and more robust"""
|
|
120
|
+
if not DASH_CYTOSCAPE_AVAILABLE:
|
|
121
|
+
raise ImportError(
|
|
122
|
+
'Network visualization requires optional dependencies. '
|
|
123
|
+
'Install with: pip install flixopt[viz] or '
|
|
124
|
+
'pip install dash dash-cytoscape networkx werkzeug. '
|
|
125
|
+
f'Original error: {VISUALIZATION_ERROR}'
|
|
126
|
+
)
|
|
127
|
+
|
|
115
128
|
nodes = list(flow_system.components.values()) + list(flow_system.buses.values())
|
|
116
129
|
edges = list(flow_system.flows.values())
|
|
117
130
|
|
|
@@ -141,7 +154,7 @@ def flow_graph(flow_system: FlowSystem) -> networkx.DiGraph:
|
|
|
141
154
|
else:
|
|
142
155
|
return 'rectangle'
|
|
143
156
|
|
|
144
|
-
graph =
|
|
157
|
+
graph = nx.DiGraph()
|
|
145
158
|
|
|
146
159
|
# Add nodes with attributes
|
|
147
160
|
for node in nodes:
|
|
@@ -168,7 +181,7 @@ def flow_graph(flow_system: FlowSystem) -> networkx.DiGraph:
|
|
|
168
181
|
return graph
|
|
169
182
|
|
|
170
183
|
|
|
171
|
-
def make_cytoscape_elements(graph:
|
|
184
|
+
def make_cytoscape_elements(graph: nx.DiGraph) -> list[dict[str, Any]]:
|
|
172
185
|
"""Convert NetworkX graph to Cytoscape elements"""
|
|
173
186
|
elements = []
|
|
174
187
|
|
|
@@ -225,7 +238,7 @@ def create_color_picker_input(label: str, input_id: str, default_color: str):
|
|
|
225
238
|
)
|
|
226
239
|
|
|
227
240
|
|
|
228
|
-
def create_style_section(title: str, children:
|
|
241
|
+
def create_style_section(title: str, children: list):
|
|
229
242
|
"""Create a collapsible section for organizing controls"""
|
|
230
243
|
return html.Div(
|
|
231
244
|
[
|
|
@@ -378,7 +391,7 @@ def create_sidebar():
|
|
|
378
391
|
)
|
|
379
392
|
|
|
380
393
|
|
|
381
|
-
def shownetwork(graph:
|
|
394
|
+
def shownetwork(graph: nx.DiGraph):
|
|
382
395
|
"""Main function to create and run the network visualization"""
|
|
383
396
|
if not DASH_CYTOSCAPE_AVAILABLE:
|
|
384
397
|
raise ImportError(f'Required packages not available: {VISUALIZATION_ERROR}')
|
|
@@ -535,10 +548,46 @@ def shownetwork(graph: networkx.DiGraph):
|
|
|
535
548
|
|
|
536
549
|
return sidebar_style, main_style
|
|
537
550
|
|
|
551
|
+
# Combined callback to handle both color scheme changes and reset
|
|
552
|
+
@app.callback(
|
|
553
|
+
[
|
|
554
|
+
Output('bus-color-picker', 'value'),
|
|
555
|
+
Output('source-color-picker', 'value'),
|
|
556
|
+
Output('sink-color-picker', 'value'),
|
|
557
|
+
Output('storage-color-picker', 'value'),
|
|
558
|
+
Output('converter-color-picker', 'value'),
|
|
559
|
+
],
|
|
560
|
+
[Input('color-scheme-dropdown', 'value'), Input('reset-btn', 'n_clicks')],
|
|
561
|
+
)
|
|
562
|
+
def update_color_pickers(color_scheme, reset_clicks):
|
|
563
|
+
"""Update color pickers when color scheme changes or reset is clicked"""
|
|
564
|
+
ctx = callback_context
|
|
565
|
+
|
|
566
|
+
# Determine which input triggered the callback
|
|
567
|
+
if ctx.triggered:
|
|
568
|
+
trigger_id = ctx.triggered[0]['prop_id'].split('.')[0]
|
|
569
|
+
if trigger_id == 'reset-btn' and reset_clicks and reset_clicks > 0:
|
|
570
|
+
# Reset was clicked, use default colors
|
|
571
|
+
colors = VisualizationConfig.DEFAULT_COLORS
|
|
572
|
+
else:
|
|
573
|
+
# Color scheme changed
|
|
574
|
+
colors = VisualizationConfig.COLOR_PRESETS.get(color_scheme, VisualizationConfig.DEFAULT_COLORS)
|
|
575
|
+
else:
|
|
576
|
+
# Initial load
|
|
577
|
+
colors = VisualizationConfig.COLOR_PRESETS.get(color_scheme, VisualizationConfig.DEFAULT_COLORS)
|
|
578
|
+
|
|
579
|
+
return (
|
|
580
|
+
{'hex': colors['Bus']},
|
|
581
|
+
{'hex': colors['Source']},
|
|
582
|
+
{'hex': colors['Sink']},
|
|
583
|
+
{'hex': colors['Storage']},
|
|
584
|
+
{'hex': colors['Converter']},
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
# Updated main visualization callback - simplified logic
|
|
538
588
|
@app.callback(
|
|
539
589
|
[Output('cytoscape', 'elements'), Output('cytoscape', 'stylesheet')],
|
|
540
590
|
[
|
|
541
|
-
Input('color-scheme-dropdown', 'value'),
|
|
542
591
|
Input('bus-color-picker', 'value'),
|
|
543
592
|
Input('source-color-picker', 'value'),
|
|
544
593
|
Input('sink-color-picker', 'value'),
|
|
@@ -551,7 +600,6 @@ def shownetwork(graph: networkx.DiGraph):
|
|
|
551
600
|
[State('elements-store', 'data')],
|
|
552
601
|
)
|
|
553
602
|
def update_visualization(
|
|
554
|
-
color_scheme,
|
|
555
603
|
bus_color,
|
|
556
604
|
source_color,
|
|
557
605
|
sink_color,
|
|
@@ -562,23 +610,20 @@ def shownetwork(graph: networkx.DiGraph):
|
|
|
562
610
|
font_size,
|
|
563
611
|
stored_elements,
|
|
564
612
|
):
|
|
613
|
+
"""Update visualization based on current color picker values"""
|
|
565
614
|
if not stored_elements:
|
|
566
615
|
return no_update, no_update
|
|
567
616
|
|
|
568
|
-
#
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
}
|
|
579
|
-
else:
|
|
580
|
-
# Use preset scheme
|
|
581
|
-
colors = VisualizationConfig.COLOR_PRESETS.get(color_scheme, VisualizationConfig.DEFAULT_COLORS)
|
|
617
|
+
# Use colors from pickers (which are now synced with scheme selection)
|
|
618
|
+
default_colors = VisualizationConfig.DEFAULT_COLORS
|
|
619
|
+
colors = {
|
|
620
|
+
'Bus': bus_color.get('hex') if bus_color else default_colors['Bus'],
|
|
621
|
+
'Source': source_color.get('hex') if source_color else default_colors['Source'],
|
|
622
|
+
'Sink': sink_color.get('hex') if sink_color else default_colors['Sink'],
|
|
623
|
+
'Storage': storage_color.get('hex') if storage_color else default_colors['Storage'],
|
|
624
|
+
'Converter': converter_color.get('hex') if converter_color else default_colors['Converter'],
|
|
625
|
+
'Other': default_colors['Other'],
|
|
626
|
+
}
|
|
582
627
|
|
|
583
628
|
# Update element colors
|
|
584
629
|
updated_elements = []
|
|
@@ -681,15 +726,10 @@ def shownetwork(graph: networkx.DiGraph):
|
|
|
681
726
|
def update_layout(selected_layout):
|
|
682
727
|
return {'name': selected_layout}
|
|
683
728
|
|
|
684
|
-
# Reset callback
|
|
729
|
+
# Reset callback for non-color-picker controls
|
|
685
730
|
@app.callback(
|
|
686
731
|
[
|
|
687
732
|
Output('color-scheme-dropdown', 'value'),
|
|
688
|
-
Output('bus-color-picker', 'value'),
|
|
689
|
-
Output('source-color-picker', 'value'),
|
|
690
|
-
Output('sink-color-picker', 'value'),
|
|
691
|
-
Output('storage-color-picker', 'value'),
|
|
692
|
-
Output('converter-color-picker', 'value'),
|
|
693
733
|
Output('edge-color-picker', 'value'),
|
|
694
734
|
Output('node-size-slider', 'value'),
|
|
695
735
|
Output('font-size-slider', 'value'),
|
|
@@ -698,15 +738,11 @@ def shownetwork(graph: networkx.DiGraph):
|
|
|
698
738
|
[Input('reset-btn', 'n_clicks')],
|
|
699
739
|
)
|
|
700
740
|
def reset_controls(n_clicks):
|
|
741
|
+
"""Reset all controls to defaults (color pickers handled separately)"""
|
|
701
742
|
if n_clicks and n_clicks > 0:
|
|
702
743
|
return (
|
|
703
|
-
'Default', # color scheme
|
|
704
|
-
{'hex': '#
|
|
705
|
-
{'hex': '#F1C40F'}, # source
|
|
706
|
-
{'hex': '#F1C40F'}, # sink
|
|
707
|
-
{'hex': '#2980B9'}, # storage
|
|
708
|
-
{'hex': '#D35400'}, # converter
|
|
709
|
-
{'hex': '#808080'}, # edge
|
|
744
|
+
'Default', # color scheme (will trigger color picker updates)
|
|
745
|
+
{'hex': '#808080'}, # edge color
|
|
710
746
|
90, # node size
|
|
711
747
|
10, # font size
|
|
712
748
|
'klay', # layout
|