webviz-subsurface 0.2.30__py3-none-any.whl → 0.2.32__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.
- webviz_subsurface/_components/tornado/_tornado_data.py +3 -0
- webviz_subsurface/_providers/ensemble_surface_provider/surface_array_server.py +0 -1
- webviz_subsurface/_providers/ensemble_surface_provider/surface_image_server.py +2 -7
- webviz_subsurface/plugins/_co2_leakage/_plugin.py +79 -37
- webviz_subsurface/plugins/_co2_leakage/_utilities/callbacks.py +99 -38
- webviz_subsurface/plugins/_co2_leakage/_utilities/co2volume.py +417 -355
- webviz_subsurface/plugins/_co2_leakage/_utilities/generic.py +2 -7
- webviz_subsurface/plugins/_co2_leakage/_utilities/initialization.py +15 -11
- webviz_subsurface/plugins/_co2_leakage/_utilities/surface_publishing.py +13 -4
- webviz_subsurface/plugins/_co2_leakage/views/mainview/mainview.py +93 -33
- webviz_subsurface/plugins/_co2_leakage/views/mainview/settings.py +301 -116
- webviz_subsurface/plugins/_volumetric_analysis/controllers/tornado_controllers.py +5 -1
- {webviz_subsurface-0.2.30.dist-info → webviz_subsurface-0.2.32.dist-info}/METADATA +34 -34
- {webviz_subsurface-0.2.30.dist-info → webviz_subsurface-0.2.32.dist-info}/RECORD +19 -19
- {webviz_subsurface-0.2.30.dist-info → webviz_subsurface-0.2.32.dist-info}/WHEEL +1 -1
- {webviz_subsurface-0.2.30.dist-info → webviz_subsurface-0.2.32.dist-info}/LICENSE +0 -0
- {webviz_subsurface-0.2.30.dist-info → webviz_subsurface-0.2.32.dist-info}/LICENSE.chromedriver +0 -0
- {webviz_subsurface-0.2.30.dist-info → webviz_subsurface-0.2.32.dist-info}/entry_points.txt +0 -0
- {webviz_subsurface-0.2.30.dist-info → webviz_subsurface-0.2.32.dist-info}/top_level.txt +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# pylint: disable=too-many-lines
|
|
1
2
|
import warnings
|
|
2
3
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
3
4
|
|
|
@@ -14,7 +15,6 @@ from webviz_subsurface._providers.ensemble_surface_provider.ensemble_surface_pro
|
|
|
14
15
|
from webviz_subsurface.plugins._co2_leakage._utilities.callbacks import property_origin
|
|
15
16
|
from webviz_subsurface.plugins._co2_leakage._utilities.generic import (
|
|
16
17
|
Co2MassScale,
|
|
17
|
-
ContainmentViews,
|
|
18
18
|
GraphSource,
|
|
19
19
|
LayoutLabels,
|
|
20
20
|
LayoutStyle,
|
|
@@ -48,9 +48,18 @@ class ViewSettings(SettingsGroupABC):
|
|
|
48
48
|
Y_MAX_GRAPH = "y-max-graph"
|
|
49
49
|
Y_MIN_AUTO_GRAPH = "y-min-auto-graph"
|
|
50
50
|
Y_MAX_AUTO_GRAPH = "y-max-auto-graph"
|
|
51
|
+
COLOR_BY = "color-by"
|
|
52
|
+
MARK_BY = "mark-by"
|
|
53
|
+
SORT_PLOT = "sort-plot"
|
|
51
54
|
ZONE = "zone"
|
|
55
|
+
ZONE_COL = "zone-column"
|
|
56
|
+
REGION_COL = "region-column"
|
|
57
|
+
ZONE_REGION = "zone-and-region"
|
|
52
58
|
REGION = "region"
|
|
53
|
-
|
|
59
|
+
PHASE = "phase"
|
|
60
|
+
PHASE_MENU = "phase-menu"
|
|
61
|
+
CONTAINMENT = "containment"
|
|
62
|
+
CONTAINMENT_MENU = "containment-menu"
|
|
54
63
|
|
|
55
64
|
PLUME_THRESHOLD = "plume-threshold"
|
|
56
65
|
PLUME_SMOOTHING = "plume-smoothing"
|
|
@@ -70,7 +79,7 @@ class ViewSettings(SettingsGroupABC):
|
|
|
70
79
|
map_attribute_names: Dict[MapAttribute, str],
|
|
71
80
|
color_scale_names: List[str],
|
|
72
81
|
well_names_dict: Dict[str, List[str]],
|
|
73
|
-
|
|
82
|
+
menu_options: Dict[str, Dict[str, Dict[str, List[str]]]],
|
|
74
83
|
):
|
|
75
84
|
super().__init__("Settings")
|
|
76
85
|
self._ensemble_paths = ensemble_paths
|
|
@@ -79,15 +88,15 @@ class ViewSettings(SettingsGroupABC):
|
|
|
79
88
|
self._color_scale_names = color_scale_names
|
|
80
89
|
self._initial_surface = initial_surface
|
|
81
90
|
self._well_names_dict = well_names_dict
|
|
82
|
-
self.
|
|
91
|
+
self._menu_options = menu_options
|
|
83
92
|
self._has_zones = max(
|
|
84
93
|
len(inner_dict["zones"]) > 0
|
|
85
|
-
for outer_dict in
|
|
94
|
+
for outer_dict in menu_options.values()
|
|
86
95
|
for inner_dict in outer_dict.values()
|
|
87
96
|
)
|
|
88
97
|
self._has_regions = max(
|
|
89
98
|
len(inner_dict["regions"]) > 0
|
|
90
|
-
for outer_dict in
|
|
99
|
+
for outer_dict in menu_options.values()
|
|
91
100
|
for inner_dict in outer_dict.values()
|
|
92
101
|
)
|
|
93
102
|
|
|
@@ -126,9 +135,18 @@ class ViewSettings(SettingsGroupABC):
|
|
|
126
135
|
self.register_component_unique_id(self.Ids.Y_MAX_AUTO_GRAPH),
|
|
127
136
|
],
|
|
128
137
|
[
|
|
138
|
+
self.register_component_unique_id(self.Ids.COLOR_BY),
|
|
139
|
+
self.register_component_unique_id(self.Ids.MARK_BY),
|
|
140
|
+
self.register_component_unique_id(self.Ids.SORT_PLOT),
|
|
129
141
|
self.register_component_unique_id(self.Ids.ZONE),
|
|
142
|
+
self.register_component_unique_id(self.Ids.ZONE_COL),
|
|
130
143
|
self.register_component_unique_id(self.Ids.REGION),
|
|
131
|
-
self.register_component_unique_id(self.Ids.
|
|
144
|
+
self.register_component_unique_id(self.Ids.REGION_COL),
|
|
145
|
+
self.register_component_unique_id(self.Ids.ZONE_REGION),
|
|
146
|
+
self.register_component_unique_id(self.Ids.PHASE),
|
|
147
|
+
self.register_component_unique_id(self.Ids.PHASE_MENU),
|
|
148
|
+
self.register_component_unique_id(self.Ids.CONTAINMENT),
|
|
149
|
+
self.register_component_unique_id(self.Ids.CONTAINMENT_MENU),
|
|
132
150
|
],
|
|
133
151
|
self._has_zones,
|
|
134
152
|
self._has_regions,
|
|
@@ -173,10 +191,14 @@ class ViewSettings(SettingsGroupABC):
|
|
|
173
191
|
prop_name = property_origin(MapAttribute(prop), self._map_attribute_names)
|
|
174
192
|
surfaces = surface_provider.surface_names_for_attribute(prop_name)
|
|
175
193
|
if len(surfaces) == 0:
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
194
|
+
warning = f"Surface not found for property: {prop}.\n"
|
|
195
|
+
warning += f"Expected name: <formation>--{prop_name}"
|
|
196
|
+
if MapAttribute(prop) not in [
|
|
197
|
+
MapAttribute.MIGRATION_TIME_SGAS,
|
|
198
|
+
MapAttribute.MIGRATION_TIME_AMFG,
|
|
199
|
+
]:
|
|
200
|
+
warning += "--<date>"
|
|
201
|
+
warnings.warn(warning + ".gri")
|
|
180
202
|
# Formation names
|
|
181
203
|
formations = [{"label": v.title(), "value": v} for v in surfaces]
|
|
182
204
|
picked_formation = None
|
|
@@ -229,7 +251,10 @@ class ViewSettings(SettingsGroupABC):
|
|
|
229
251
|
Input(self.component_unique_id(self.Ids.PROPERTY).to_string(), "value"),
|
|
230
252
|
)
|
|
231
253
|
def set_visualization_threshold(attribute: str) -> bool:
|
|
232
|
-
return MapAttribute(attribute)
|
|
254
|
+
return MapAttribute(attribute) in [
|
|
255
|
+
MapAttribute.MIGRATION_TIME_SGAS,
|
|
256
|
+
MapAttribute.MIGRATION_TIME_AMFG,
|
|
257
|
+
]
|
|
233
258
|
|
|
234
259
|
@callback(
|
|
235
260
|
Output(
|
|
@@ -250,6 +275,24 @@ class ViewSettings(SettingsGroupABC):
|
|
|
250
275
|
) -> Tuple[bool, bool]:
|
|
251
276
|
return len(min_auto) == 1, len(max_auto) == 1
|
|
252
277
|
|
|
278
|
+
@callback(
|
|
279
|
+
Output(self.component_unique_id(self.Ids.PHASE).to_string(), "options"),
|
|
280
|
+
Output(self.component_unique_id(self.Ids.PHASE).to_string(), "value"),
|
|
281
|
+
Input(self.component_unique_id(self.Ids.GRAPH_SOURCE).to_string(), "value"),
|
|
282
|
+
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
283
|
+
State(self.component_unique_id(self.Ids.PHASE).to_string(), "value"),
|
|
284
|
+
)
|
|
285
|
+
def set_phases(
|
|
286
|
+
source: GraphSource,
|
|
287
|
+
ensemble: str,
|
|
288
|
+
current_value: str,
|
|
289
|
+
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
290
|
+
if ensemble is not None:
|
|
291
|
+
phases = self._menu_options[ensemble][source]["phases"]
|
|
292
|
+
options = [{"label": phase.title(), "value": phase} for phase in phases]
|
|
293
|
+
return options, no_update if current_value in phases else "total"
|
|
294
|
+
return [], "total"
|
|
295
|
+
|
|
253
296
|
@callback(
|
|
254
297
|
Output(self.component_unique_id(self.Ids.ZONE).to_string(), "options"),
|
|
255
298
|
Output(self.component_unique_id(self.Ids.ZONE).to_string(), "value"),
|
|
@@ -263,26 +306,11 @@ class ViewSettings(SettingsGroupABC):
|
|
|
263
306
|
current_value: str,
|
|
264
307
|
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
265
308
|
if ensemble is not None:
|
|
266
|
-
zones = self.
|
|
309
|
+
zones = self._menu_options[ensemble][source]["zones"]
|
|
267
310
|
if len(zones) > 0:
|
|
268
311
|
options = [{"label": zone.title(), "value": zone} for zone in zones]
|
|
269
312
|
return options, no_update if current_value in zones else "all"
|
|
270
|
-
return [],
|
|
271
|
-
|
|
272
|
-
@callback(
|
|
273
|
-
Output(self.component_unique_id(self.Ids.ZONE).to_string(), "disabled"),
|
|
274
|
-
Input(self.component_unique_id(self.Ids.ZONE).to_string(), "value"),
|
|
275
|
-
Input(self.component_unique_id(self.Ids.REGION).to_string(), "value"),
|
|
276
|
-
Input(
|
|
277
|
-
self.component_unique_id(self.Ids.CONTAINMENT_VIEW).to_string(), "value"
|
|
278
|
-
),
|
|
279
|
-
)
|
|
280
|
-
def disable_zone(zone: str, region: str, containment_view: str) -> bool:
|
|
281
|
-
return (
|
|
282
|
-
zone is None
|
|
283
|
-
or containment_view != ContainmentViews.CONTAINMENTSPLIT
|
|
284
|
-
or (region is not None and region != "all")
|
|
285
|
-
)
|
|
313
|
+
return [], "all"
|
|
286
314
|
|
|
287
315
|
@callback(
|
|
288
316
|
Output(self.component_unique_id(self.Ids.REGION).to_string(), "options"),
|
|
@@ -297,26 +325,11 @@ class ViewSettings(SettingsGroupABC):
|
|
|
297
325
|
current_value: str,
|
|
298
326
|
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
299
327
|
if ensemble is not None:
|
|
300
|
-
regions = self.
|
|
328
|
+
regions = self._menu_options[ensemble][source]["regions"]
|
|
301
329
|
if len(regions) > 0:
|
|
302
330
|
options = [{"label": reg.title(), "value": reg} for reg in regions]
|
|
303
331
|
return options, no_update if current_value in regions else "all"
|
|
304
|
-
return [],
|
|
305
|
-
|
|
306
|
-
@callback(
|
|
307
|
-
Output(self.component_unique_id(self.Ids.REGION).to_string(), "disabled"),
|
|
308
|
-
Input(self.component_unique_id(self.Ids.REGION).to_string(), "value"),
|
|
309
|
-
Input(self.component_unique_id(self.Ids.ZONE).to_string(), "value"),
|
|
310
|
-
Input(
|
|
311
|
-
self.component_unique_id(self.Ids.CONTAINMENT_VIEW).to_string(), "value"
|
|
312
|
-
),
|
|
313
|
-
)
|
|
314
|
-
def disable_region(region: str, zone: str, containment_view: str) -> bool:
|
|
315
|
-
return (
|
|
316
|
-
region is None
|
|
317
|
-
or containment_view != ContainmentViews.CONTAINMENTSPLIT
|
|
318
|
-
or (zone is not None and zone != "all")
|
|
319
|
-
)
|
|
332
|
+
return [], "all"
|
|
320
333
|
|
|
321
334
|
@callback(
|
|
322
335
|
Output(
|
|
@@ -334,34 +347,49 @@ class ViewSettings(SettingsGroupABC):
|
|
|
334
347
|
return False
|
|
335
348
|
|
|
336
349
|
@callback(
|
|
337
|
-
Output(
|
|
338
|
-
Output(
|
|
339
|
-
Output(
|
|
340
|
-
Output(
|
|
341
|
-
|
|
342
|
-
|
|
350
|
+
Output(self.component_unique_id(self.Ids.MARK_BY).to_string(), "options"),
|
|
351
|
+
Output(self.component_unique_id(self.Ids.MARK_BY).to_string(), "value"),
|
|
352
|
+
Output(self.component_unique_id(self.Ids.ZONE_COL).to_string(), "style"),
|
|
353
|
+
Output(self.component_unique_id(self.Ids.REGION_COL).to_string(), "style"),
|
|
354
|
+
Output(self.component_unique_id(self.Ids.PHASE_MENU).to_string(), "style"),
|
|
355
|
+
Output(
|
|
356
|
+
self.component_unique_id(self.Ids.CONTAINMENT_MENU).to_string(),
|
|
357
|
+
"style",
|
|
343
358
|
),
|
|
359
|
+
Input(self.component_unique_id(self.Ids.COLOR_BY).to_string(), "value"),
|
|
360
|
+
Input(self.component_unique_id(self.Ids.MARK_BY).to_string(), "value"),
|
|
344
361
|
)
|
|
345
|
-
def
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
{
|
|
353
|
-
"width": "50%" if self._has_regions else "100%",
|
|
354
|
-
"display": disp_zone,
|
|
355
|
-
"flex-direction": "column",
|
|
356
|
-
},
|
|
357
|
-
{
|
|
358
|
-
"width": "50%" if self._has_zones else "100%",
|
|
359
|
-
"display": disp_region,
|
|
360
|
-
"flex-direction": "column",
|
|
361
|
-
},
|
|
362
|
-
{"display": disp_either},
|
|
363
|
-
{"display": disp_either},
|
|
362
|
+
def organize_color_and_mark_menus(
|
|
363
|
+
color_choice: str,
|
|
364
|
+
mark_choice: str,
|
|
365
|
+
) -> Tuple[List[Dict], str, Dict, Dict, Dict, Dict]:
|
|
366
|
+
mark_options = [
|
|
367
|
+
{"label": "Phase", "value": "phase"},
|
|
368
|
+
{"label": "None", "value": "none"},
|
|
364
369
|
]
|
|
370
|
+
if self._has_zones and color_choice == "containment":
|
|
371
|
+
mark_options.append({"label": "Zone", "value": "zone"})
|
|
372
|
+
if self._has_regions and color_choice == "containment":
|
|
373
|
+
mark_options.append({"label": "Region", "value": "region"})
|
|
374
|
+
if color_choice in ["zone", "region"]:
|
|
375
|
+
mark_options.append({"label": "Containment", "value": "containment"})
|
|
376
|
+
if mark_choice is None or mark_choice == color_choice:
|
|
377
|
+
mark_choice = "phase"
|
|
378
|
+
if mark_choice in ["zone", "region"] and color_choice in ["zone", "region"]:
|
|
379
|
+
mark_choice = "phase"
|
|
380
|
+
zone, region, phase, containment = _make_styles(
|
|
381
|
+
color_choice, mark_choice, self._has_zones, self._has_regions
|
|
382
|
+
)
|
|
383
|
+
return mark_options, mark_choice, zone, region, phase, containment
|
|
384
|
+
|
|
385
|
+
@callback(
|
|
386
|
+
Output(self.component_unique_id(self.Ids.ZONE).to_string(), "disabled"),
|
|
387
|
+
Output(self.component_unique_id(self.Ids.REGION).to_string(), "disabled"),
|
|
388
|
+
Input(self.component_unique_id(self.Ids.ZONE).to_string(), "value"),
|
|
389
|
+
Input(self.component_unique_id(self.Ids.REGION).to_string(), "value"),
|
|
390
|
+
)
|
|
391
|
+
def disable_zone_or_region(zone: str, region: str) -> Tuple[bool, bool]:
|
|
392
|
+
return region != "all", zone != "all"
|
|
365
393
|
|
|
366
394
|
|
|
367
395
|
class OpenDialogButton(html.Button):
|
|
@@ -492,7 +520,7 @@ class MapSelectorLayout(wcc.Selectors):
|
|
|
492
520
|
wcc.Dropdown(
|
|
493
521
|
id=property_id,
|
|
494
522
|
options=_compile_property_options(),
|
|
495
|
-
value=MapAttribute.
|
|
523
|
+
value=MapAttribute.MIGRATION_TIME_SGAS.value,
|
|
496
524
|
clearable=False,
|
|
497
525
|
),
|
|
498
526
|
"Statistic",
|
|
@@ -588,35 +616,25 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
588
616
|
has_zones: bool,
|
|
589
617
|
has_regions: bool,
|
|
590
618
|
):
|
|
591
|
-
disp = "flex" if has_zones or has_regions else "none"
|
|
592
619
|
disp_zone = "flex" if has_zones else "none"
|
|
593
620
|
disp_region = "flex" if has_regions else "none"
|
|
594
|
-
only_zone = has_zones and not has_regions
|
|
595
|
-
only_region = has_regions and not has_zones
|
|
596
621
|
header = "Containment for specific"
|
|
597
|
-
if
|
|
622
|
+
if has_zones and not has_regions:
|
|
598
623
|
header += " zone"
|
|
599
|
-
elif
|
|
624
|
+
elif has_regions and not has_zones:
|
|
600
625
|
header += " region"
|
|
601
|
-
|
|
626
|
+
color_options = [{"label": "Containment (standard)", "value": "containment"}]
|
|
627
|
+
mark_options = [{"label": "Phase", "value": "phase"}]
|
|
602
628
|
if has_zones:
|
|
603
|
-
|
|
629
|
+
color_options.append({"label": "Zone", "value": "zone"})
|
|
630
|
+
mark_options.append({"label": "Zone", "value": "zone"})
|
|
604
631
|
if has_regions:
|
|
605
|
-
|
|
632
|
+
color_options.append({"label": "Region", "value": "region"})
|
|
633
|
+
mark_options.append({"label": "Region", "value": "region"})
|
|
606
634
|
super().__init__(
|
|
607
635
|
label="Graph Settings",
|
|
608
636
|
open_details=False,
|
|
609
637
|
children=[
|
|
610
|
-
html.Div(
|
|
611
|
-
[
|
|
612
|
-
dcc.RadioItems(
|
|
613
|
-
options,
|
|
614
|
-
ContainmentViews.CONTAINMENTSPLIT,
|
|
615
|
-
id=containment_ids[2],
|
|
616
|
-
),
|
|
617
|
-
],
|
|
618
|
-
style={"display": disp, "flex-direction": "column"},
|
|
619
|
-
),
|
|
620
638
|
"Source",
|
|
621
639
|
wcc.Dropdown(
|
|
622
640
|
id=graph_source_id,
|
|
@@ -624,51 +642,141 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
624
642
|
value=GraphSource.CONTAINMENT_MASS,
|
|
625
643
|
clearable=False,
|
|
626
644
|
),
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
id=
|
|
630
|
-
|
|
645
|
+
"Unit",
|
|
646
|
+
wcc.Dropdown(
|
|
647
|
+
id=co2_scale_id,
|
|
648
|
+
options=list(Co2MassScale),
|
|
649
|
+
value=Co2MassScale.MTONS,
|
|
650
|
+
clearable=False,
|
|
631
651
|
),
|
|
632
652
|
html.Div(
|
|
633
653
|
[
|
|
634
654
|
html.Div(
|
|
635
|
-
|
|
636
|
-
|
|
655
|
+
[
|
|
656
|
+
"Color by",
|
|
637
657
|
wcc.Dropdown(
|
|
658
|
+
options=color_options,
|
|
659
|
+
value="containment",
|
|
638
660
|
id=containment_ids[0],
|
|
639
661
|
clearable=False,
|
|
640
662
|
),
|
|
641
663
|
],
|
|
642
|
-
|
|
664
|
+
style={
|
|
665
|
+
"width": "50%",
|
|
666
|
+
"flex-direction": "column",
|
|
667
|
+
},
|
|
668
|
+
),
|
|
669
|
+
html.Div(
|
|
670
|
+
[
|
|
671
|
+
"Mark by",
|
|
672
|
+
wcc.Dropdown(
|
|
673
|
+
options=mark_options,
|
|
674
|
+
value="phase",
|
|
675
|
+
id=containment_ids[1],
|
|
676
|
+
clearable=False,
|
|
677
|
+
),
|
|
678
|
+
],
|
|
679
|
+
style={
|
|
680
|
+
"width": "50%",
|
|
681
|
+
"flex-direction": "column",
|
|
682
|
+
},
|
|
683
|
+
),
|
|
684
|
+
],
|
|
685
|
+
style={
|
|
686
|
+
"display": "flex", # disp,
|
|
687
|
+
"flex-direction": "row",
|
|
688
|
+
"margin-top": "10px",
|
|
689
|
+
"margin-bottom": "1px",
|
|
690
|
+
},
|
|
691
|
+
),
|
|
692
|
+
html.Div(
|
|
693
|
+
[
|
|
694
|
+
"Sort by",
|
|
695
|
+
dcc.RadioItems(
|
|
696
|
+
options=["color", "marking"],
|
|
697
|
+
value="color",
|
|
698
|
+
id=containment_ids[2],
|
|
699
|
+
inline=True,
|
|
700
|
+
),
|
|
701
|
+
],
|
|
702
|
+
style={
|
|
703
|
+
"display": "flex",
|
|
704
|
+
"flex-direction": "row",
|
|
705
|
+
"margin-top": "5px",
|
|
706
|
+
"margin-bottom": "1px",
|
|
707
|
+
},
|
|
708
|
+
),
|
|
709
|
+
html.Div(
|
|
710
|
+
[
|
|
711
|
+
html.Div(
|
|
712
|
+
[
|
|
713
|
+
"Zone",
|
|
714
|
+
wcc.Dropdown(
|
|
715
|
+
value="all",
|
|
716
|
+
id=containment_ids[3],
|
|
717
|
+
clearable=False,
|
|
718
|
+
),
|
|
719
|
+
],
|
|
720
|
+
id=containment_ids[4],
|
|
643
721
|
style={
|
|
644
722
|
"width": "50%" if has_regions else "100%",
|
|
645
723
|
"display": disp_zone,
|
|
724
|
+
"flex-direction": "column",
|
|
646
725
|
},
|
|
647
726
|
),
|
|
648
727
|
html.Div(
|
|
649
|
-
|
|
650
|
-
|
|
728
|
+
[
|
|
729
|
+
"Region",
|
|
651
730
|
wcc.Dropdown(
|
|
652
|
-
|
|
731
|
+
value="all",
|
|
732
|
+
id=containment_ids[5],
|
|
653
733
|
clearable=False,
|
|
654
734
|
),
|
|
655
735
|
],
|
|
656
|
-
id=
|
|
736
|
+
id=containment_ids[6],
|
|
657
737
|
style={
|
|
658
738
|
"width": "50%" if has_zones else "100%",
|
|
659
739
|
"display": disp_region,
|
|
740
|
+
"flex-direction": "column",
|
|
660
741
|
},
|
|
661
742
|
),
|
|
743
|
+
html.Div(
|
|
744
|
+
[
|
|
745
|
+
"Phase",
|
|
746
|
+
wcc.Dropdown(
|
|
747
|
+
value="total",
|
|
748
|
+
clearable=False,
|
|
749
|
+
id=containment_ids[8],
|
|
750
|
+
),
|
|
751
|
+
],
|
|
752
|
+
id=containment_ids[9],
|
|
753
|
+
style={"display": "none"},
|
|
754
|
+
),
|
|
755
|
+
html.Div(
|
|
756
|
+
[
|
|
757
|
+
"Containment",
|
|
758
|
+
wcc.Dropdown(
|
|
759
|
+
options=[
|
|
760
|
+
{"label": "Total", "value": "total"},
|
|
761
|
+
{"label": "Contained", "value": "contained"},
|
|
762
|
+
{"label": "Outside", "value": "outside"},
|
|
763
|
+
{"label": "Hazardous", "value": "hazardous"},
|
|
764
|
+
],
|
|
765
|
+
value="total",
|
|
766
|
+
clearable=False,
|
|
767
|
+
id=containment_ids[10],
|
|
768
|
+
),
|
|
769
|
+
],
|
|
770
|
+
id=containment_ids[11],
|
|
771
|
+
style={"display": "none"},
|
|
772
|
+
),
|
|
662
773
|
],
|
|
663
|
-
id=
|
|
664
|
-
style={"display":
|
|
774
|
+
id=containment_ids[7],
|
|
775
|
+
style={"display": "flex"},
|
|
665
776
|
),
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
options=list(Co2MassScale),
|
|
670
|
-
value=Co2MassScale.MTONS,
|
|
671
|
-
clearable=False,
|
|
777
|
+
html.Div(
|
|
778
|
+
"Fix y-limits in third plot:",
|
|
779
|
+
style={"margin-top": "10px"},
|
|
672
780
|
),
|
|
673
781
|
"Minimum",
|
|
674
782
|
html.Div(
|
|
@@ -770,8 +878,8 @@ def _compile_property_options() -> List[Dict[str, Any]]:
|
|
|
770
878
|
"disabled": True,
|
|
771
879
|
},
|
|
772
880
|
{
|
|
773
|
-
"label": MapAttribute.
|
|
774
|
-
"value": MapAttribute.
|
|
881
|
+
"label": MapAttribute.MIGRATION_TIME_SGAS.value,
|
|
882
|
+
"value": MapAttribute.MIGRATION_TIME_SGAS.value,
|
|
775
883
|
},
|
|
776
884
|
{"label": MapAttribute.MAX_SGAS.value, "value": MapAttribute.MAX_SGAS.value},
|
|
777
885
|
{
|
|
@@ -783,6 +891,10 @@ def _compile_property_options() -> List[Dict[str, Any]]:
|
|
|
783
891
|
"value": "",
|
|
784
892
|
"disabled": True,
|
|
785
893
|
},
|
|
894
|
+
{
|
|
895
|
+
"label": MapAttribute.MIGRATION_TIME_AMFG.value,
|
|
896
|
+
"value": MapAttribute.MIGRATION_TIME_AMFG.value,
|
|
897
|
+
},
|
|
786
898
|
{"label": MapAttribute.MAX_AMFG.value, "value": MapAttribute.MAX_AMFG.value},
|
|
787
899
|
{
|
|
788
900
|
"label": MapAttribute.AMFG_PLUME.value,
|
|
@@ -800,7 +912,7 @@ def _compile_property_options() -> List[Dict[str, Any]]:
|
|
|
800
912
|
|
|
801
913
|
|
|
802
914
|
class FeedbackLayout(wcc.Dialog):
|
|
803
|
-
"""Layout for the
|
|
915
|
+
"""Layout for the feedback button"""
|
|
804
916
|
|
|
805
917
|
def __init__(
|
|
806
918
|
self,
|
|
@@ -812,9 +924,16 @@ class FeedbackLayout(wcc.Dialog):
|
|
|
812
924
|
open=False,
|
|
813
925
|
children=[
|
|
814
926
|
dcc.Markdown(
|
|
815
|
-
"""If you have any feedback regarding the CO2-
|
|
816
|
-
|
|
817
|
-
)
|
|
927
|
+
"""If you have any feedback regarding the CO2-Leakage application,
|
|
928
|
+
don't hesitate to"""
|
|
929
|
+
),
|
|
930
|
+
dcc.Link(
|
|
931
|
+
["send an email!"],
|
|
932
|
+
href=f"mailto:{get_emails()}&subject=Feedback regarding the "
|
|
933
|
+
f"CO2-Leakage application",
|
|
934
|
+
target="_blank",
|
|
935
|
+
style={"float": "left"},
|
|
936
|
+
),
|
|
818
937
|
],
|
|
819
938
|
)
|
|
820
939
|
|
|
@@ -822,10 +941,76 @@ class FeedbackLayout(wcc.Dialog):
|
|
|
822
941
|
class FeedbackButton(html.Button):
|
|
823
942
|
def __init__(self) -> None:
|
|
824
943
|
style = LayoutStyle.FEEDBACK_BUTTON
|
|
825
|
-
style["display"] = "none"
|
|
826
944
|
super().__init__(
|
|
827
945
|
LayoutLabels.FEEDBACK,
|
|
828
946
|
id=ViewSettings.Ids.FEEDBACK_BUTTON,
|
|
829
947
|
style=style,
|
|
830
948
|
n_clicks=0,
|
|
831
949
|
)
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
def decrypt_email(encrypted_email: str, key: int) -> str:
|
|
953
|
+
decrypted_email = []
|
|
954
|
+
for char in encrypted_email:
|
|
955
|
+
decrypted_email.append(chr(ord(char) ^ key))
|
|
956
|
+
return "".join(decrypted_email)
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
def get_emails() -> str:
|
|
960
|
+
emails = [
|
|
961
|
+
decrypt_email(m, i + 1)
|
|
962
|
+
for i, m in enumerate(
|
|
963
|
+
[
|
|
964
|
+
"GLLNAdpthons/bnl",
|
|
965
|
+
"OLCIKBgswklmp,amo",
|
|
966
|
+
"pfhCmq-ml",
|
|
967
|
+
"bjarnajDjv*jk",
|
|
968
|
+
"vlfdfmdEkw+kj",
|
|
969
|
+
]
|
|
970
|
+
)
|
|
971
|
+
]
|
|
972
|
+
return ";".join(emails[:2]) + "?cc=" + ";".join(emails[2:])
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
def _make_styles(
|
|
976
|
+
color_choice: str,
|
|
977
|
+
mark_choice: str,
|
|
978
|
+
has_zones: bool,
|
|
979
|
+
has_regions: bool,
|
|
980
|
+
) -> List[Dict[str, str]]:
|
|
981
|
+
zone = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
982
|
+
region = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
983
|
+
phase = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
984
|
+
containment = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
985
|
+
if color_choice == "containment":
|
|
986
|
+
if mark_choice == "phase":
|
|
987
|
+
zone["width"] = "50%" if has_regions else "100%"
|
|
988
|
+
zone["display"] = "flex" if has_zones else "none"
|
|
989
|
+
region["width"] = "50%" if has_zones else "100%"
|
|
990
|
+
region["display"] = "flex" if has_regions else "none"
|
|
991
|
+
elif mark_choice == "none":
|
|
992
|
+
zone["width"] = "33%" if has_regions else "50%"
|
|
993
|
+
zone["display"] = "flex" if has_zones else "none"
|
|
994
|
+
region["width"] = "33%" if has_zones else "50%"
|
|
995
|
+
region["display"] = "flex" if has_regions else "none"
|
|
996
|
+
phase["width"] = (
|
|
997
|
+
"33%"
|
|
998
|
+
if has_zones and has_regions
|
|
999
|
+
else "100%"
|
|
1000
|
+
if not has_regions and not has_zones
|
|
1001
|
+
else "50%"
|
|
1002
|
+
)
|
|
1003
|
+
phase["display"] = "flex"
|
|
1004
|
+
else: # mark_choice == "zone" / "region"
|
|
1005
|
+
phase["display"] = "flex"
|
|
1006
|
+
else: # color_choice == "zone" / "region"
|
|
1007
|
+
if mark_choice == "phase":
|
|
1008
|
+
containment["display"] = "flex"
|
|
1009
|
+
elif mark_choice == "none":
|
|
1010
|
+
containment["width"] = "50%"
|
|
1011
|
+
containment["display"] = "flex"
|
|
1012
|
+
phase["width"] = "50%"
|
|
1013
|
+
phase["display"] = "flex"
|
|
1014
|
+
else: # mark == "containment"
|
|
1015
|
+
phase["display"] = "flex"
|
|
1016
|
+
return [zone, region, phase, containment]
|
|
@@ -359,12 +359,16 @@ def create_tornado_table(
|
|
|
359
359
|
use_si_format=use_si_format,
|
|
360
360
|
precision=4 if use_si_format else 3,
|
|
361
361
|
)
|
|
362
|
+
mean_col = "Mean (mc)"
|
|
362
363
|
table_data = tornado_table.as_plotly_table
|
|
363
364
|
for data in table_data:
|
|
364
|
-
data[
|
|
365
|
+
data[mean_col] = tornado_data.mean_per_mc_sens.get(data["Sensitivity"])
|
|
365
366
|
if group is not None:
|
|
366
367
|
data[subplots] = group
|
|
367
368
|
|
|
368
369
|
columns = create_table_columns(columns=[subplots]) if subplots is not None else []
|
|
369
370
|
columns.extend(tornado_table.columns)
|
|
371
|
+
columns.insert(
|
|
372
|
+
-3, create_table_columns(columns=[mean_col], use_si_format=[mean_col])[0]
|
|
373
|
+
)
|
|
370
374
|
return table_data, columns
|