webviz-subsurface 0.2.44__py3-none-any.whl → 0.2.46__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/_providers/ensemble_polygon_provider/_provider_impl_file.py +2 -1
- webviz_subsurface/_version.py +2 -2
- webviz_subsurface/plugins/_co2_migration/_plugin.py +31 -8
- webviz_subsurface/plugins/_co2_migration/_utilities/callbacks.py +183 -19
- webviz_subsurface/plugins/_co2_migration/_utilities/co2volume.py +83 -62
- webviz_subsurface/plugins/_co2_migration/_utilities/containment_data_provider.py +6 -0
- webviz_subsurface/plugins/_co2_migration/_utilities/generic.py +40 -3
- webviz_subsurface/plugins/_co2_migration/_utilities/initialization.py +2 -1
- webviz_subsurface/plugins/_co2_migration/_utilities/polygon_handler.py +4 -0
- webviz_subsurface/plugins/_co2_migration/views/mainview/settings.py +38 -3
- {webviz_subsurface-0.2.44.dist-info → webviz_subsurface-0.2.46.dist-info}/METADATA +1 -2
- {webviz_subsurface-0.2.44.dist-info → webviz_subsurface-0.2.46.dist-info}/RECORD +16 -17
- {webviz_subsurface-0.2.44.dist-info → webviz_subsurface-0.2.46.dist-info}/WHEEL +1 -1
- webviz_subsurface-0.2.44.dist-info/licenses/LICENSE.chromedriver +0 -6291
- {webviz_subsurface-0.2.44.dist-info → webviz_subsurface-0.2.46.dist-info}/entry_points.txt +0 -0
- {webviz_subsurface-0.2.44.dist-info → webviz_subsurface-0.2.46.dist-info}/licenses/LICENSE +0 -0
- {webviz_subsurface-0.2.44.dist-info → webviz_subsurface-0.2.46.dist-info}/top_level.txt +0 -0
|
@@ -33,7 +33,8 @@ class Col:
|
|
|
33
33
|
|
|
34
34
|
class PolygonType(StrEnum):
|
|
35
35
|
SIMULATED = "simulated"
|
|
36
|
-
|
|
36
|
+
HAZARDOUS_BOUNDARY = "hazardous_boundary" # Keep for backward compatibility
|
|
37
|
+
NOGO_BOUNDARY = "nogo_boundary"
|
|
37
38
|
CONTAINMENT_BOUNDARY = "containment_boundary"
|
|
38
39
|
|
|
39
40
|
|
webviz_subsurface/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.2.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
31
|
+
__version__ = version = '0.2.46'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 2, 46)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -40,6 +40,8 @@ from webviz_subsurface.plugins._co2_migration._utilities.generic import (
|
|
|
40
40
|
MapAttribute,
|
|
41
41
|
MapThresholds,
|
|
42
42
|
MapType,
|
|
43
|
+
check_hazardous_polygon,
|
|
44
|
+
deactivate_polygon_warnings,
|
|
43
45
|
)
|
|
44
46
|
from webviz_subsurface.plugins._co2_migration._utilities.initialization import (
|
|
45
47
|
init_containment_data_providers,
|
|
@@ -95,7 +97,7 @@ class CO2Migration(WebvizPluginABC):
|
|
|
95
97
|
* **`map_surface_names_to_fault_polygons`:** Mapping between surface map names and
|
|
96
98
|
surface names used by the fault polygons
|
|
97
99
|
* **`boundary_settings`:** Settings for polygons representing the containment and
|
|
98
|
-
|
|
100
|
+
nogo areas
|
|
99
101
|
---
|
|
100
102
|
|
|
101
103
|
This plugin is tightly linked to the FMU CCS post-process available in the ccs-scripts
|
|
@@ -141,17 +143,17 @@ class CO2Migration(WebvizPluginABC):
|
|
|
141
143
|
Similar for `map_surface_names_to_fault_polygons`.
|
|
142
144
|
|
|
143
145
|
`boundary_settings` is the final override option, and it can be used to specify
|
|
144
|
-
polygons representing the containment and
|
|
146
|
+
polygons representing the containment and nogo areas. By default, the polygons are
|
|
145
147
|
expected to be named:
|
|
146
148
|
- `share/results/polygons/containment--boundary.csv`
|
|
147
|
-
- `share/results/polygons/
|
|
149
|
+
- `share/results/polygons/nogo--boundary.csv`
|
|
148
150
|
|
|
149
151
|
This corresponds to the following input:
|
|
150
152
|
```
|
|
151
153
|
boundary_settings:
|
|
152
154
|
polygon_file_pattern: share/results/polygons/*.csv
|
|
153
155
|
attribute: boundary
|
|
154
|
-
|
|
156
|
+
nogo_name: nogo
|
|
155
157
|
containment_name: containment
|
|
156
158
|
```
|
|
157
159
|
All four settings are optional, and if not specified, the default values are used.
|
|
@@ -182,6 +184,8 @@ class CO2Migration(WebvizPluginABC):
|
|
|
182
184
|
super().__init__()
|
|
183
185
|
self._error_message = ""
|
|
184
186
|
try:
|
|
187
|
+
deactivate_polygon_warnings()
|
|
188
|
+
check_hazardous_polygon(boundary_settings)
|
|
185
189
|
ensemble_paths = {
|
|
186
190
|
ensemble_name: webviz_settings.shared_settings["scratch_ensembles"][
|
|
187
191
|
ensemble_name
|
|
@@ -435,6 +439,13 @@ class CO2Migration(WebvizPluginABC):
|
|
|
435
439
|
"cm_max_val": Input(
|
|
436
440
|
self._settings_component(ViewSettings.Ids.CM_MAX), "value"
|
|
437
441
|
),
|
|
442
|
+
"contour_switch": Input(
|
|
443
|
+
self._settings_component(ViewSettings.Ids.CONTOURS_SWITCH), "value"
|
|
444
|
+
),
|
|
445
|
+
"contour_quantity": Input(
|
|
446
|
+
self._settings_component(ViewSettings.Ids.CONTOURS_QUANTITY),
|
|
447
|
+
"value",
|
|
448
|
+
),
|
|
438
449
|
"plume_threshold": Input(
|
|
439
450
|
self._settings_component(ViewSettings.Ids.PLUME_THRESHOLD),
|
|
440
451
|
"value",
|
|
@@ -480,12 +491,14 @@ class CO2Migration(WebvizPluginABC):
|
|
|
480
491
|
cm_min_val: Optional[float],
|
|
481
492
|
cm_max_auto: List[str],
|
|
482
493
|
cm_max_val: Optional[float],
|
|
494
|
+
contour_switch: List[str],
|
|
495
|
+
contour_quantity: Optional[float],
|
|
483
496
|
plume_threshold: Optional[float],
|
|
484
497
|
plume_smoothing: Optional[float],
|
|
485
498
|
visualization_update: int,
|
|
486
499
|
mass_unit: str,
|
|
487
500
|
mass_unit_update: int,
|
|
488
|
-
options_dialog_options: List[
|
|
501
|
+
options_dialog_options: List[str],
|
|
489
502
|
selected_wells: List[str],
|
|
490
503
|
ensemble: str,
|
|
491
504
|
current_views: List[Any],
|
|
@@ -545,13 +558,12 @@ class CO2Migration(WebvizPluginABC):
|
|
|
545
558
|
map_attribute_names=self._map_attribute_names,
|
|
546
559
|
)
|
|
547
560
|
assert isinstance(self._visualization_info["unit"], str)
|
|
548
|
-
|
|
561
|
+
current_summed_mass, self._summed_co2 = process_summed_mass(
|
|
549
562
|
formation,
|
|
550
563
|
realization,
|
|
551
564
|
datestr,
|
|
552
565
|
attribute,
|
|
553
566
|
summed_mass,
|
|
554
|
-
surf_data,
|
|
555
567
|
self._summed_co2,
|
|
556
568
|
self._visualization_info["unit"],
|
|
557
569
|
)
|
|
@@ -568,6 +580,9 @@ class CO2Migration(WebvizPluginABC):
|
|
|
568
580
|
fault_polygon_url = self._fault_polygon_handlers[
|
|
569
581
|
ensemble
|
|
570
582
|
].extract_fault_polygon_url(formation, realization)
|
|
583
|
+
nogo_polygon_url = self._polygon_handlers[ensemble].extract_nogo_poly_url(
|
|
584
|
+
realization
|
|
585
|
+
)
|
|
571
586
|
hazardous_polygon_url = self._polygon_handlers[
|
|
572
587
|
ensemble
|
|
573
588
|
].extract_hazardous_poly_url(realization)
|
|
@@ -580,11 +595,14 @@ class CO2Migration(WebvizPluginABC):
|
|
|
580
595
|
surface_data=surf_data,
|
|
581
596
|
fault_polygon_url=fault_polygon_url,
|
|
582
597
|
containment_bounds_url=containment_polygon_url,
|
|
583
|
-
|
|
598
|
+
nogo_bounds_url=nogo_polygon_url,
|
|
599
|
+
hazardous_bounds_url=hazardous_polygon_url,
|
|
584
600
|
well_pick_provider=self._well_pick_provider.get(ensemble, None),
|
|
585
601
|
plume_extent_data=plume_polygon,
|
|
586
602
|
options_dialog_options=options_dialog_options,
|
|
587
603
|
selected_wells=selected_wells,
|
|
604
|
+
show_contours=len(contour_switch) > 0,
|
|
605
|
+
num_contours=contour_quantity,
|
|
588
606
|
)
|
|
589
607
|
annotations = create_map_annotations(
|
|
590
608
|
formation=formation,
|
|
@@ -592,6 +610,11 @@ class CO2Migration(WebvizPluginABC):
|
|
|
592
610
|
colortables=self._color_tables,
|
|
593
611
|
attribute=attribute,
|
|
594
612
|
unit=self._visualization_info["unit"],
|
|
613
|
+
current_total=current_summed_mass,
|
|
614
|
+
options=options_dialog_options,
|
|
615
|
+
con_url=containment_polygon_url,
|
|
616
|
+
haz_url=hazardous_polygon_url,
|
|
617
|
+
nogo_url=nogo_polygon_url,
|
|
595
618
|
)
|
|
596
619
|
viewports = no_update if current_views else create_map_viewports()
|
|
597
620
|
return layers, annotations, viewports
|
|
@@ -7,7 +7,7 @@ import geojson
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import plotly.graph_objects as go
|
|
9
9
|
import webviz_subsurface_components as wsc
|
|
10
|
-
from dash import dcc, no_update
|
|
10
|
+
from dash import dcc, html, no_update
|
|
11
11
|
from flask_caching import Cache
|
|
12
12
|
|
|
13
13
|
from webviz_subsurface._providers import (
|
|
@@ -234,12 +234,127 @@ def _find_legend_title(attribute: MapAttribute, unit: str) -> str:
|
|
|
234
234
|
return ""
|
|
235
235
|
|
|
236
236
|
|
|
237
|
+
def _create_summed_mass_annotation(
|
|
238
|
+
attribute: MapAttribute,
|
|
239
|
+
summed_mass: Optional[float],
|
|
240
|
+
unit: str,
|
|
241
|
+
) -> Union[str, tuple]:
|
|
242
|
+
annotation = (
|
|
243
|
+
html.P(
|
|
244
|
+
[
|
|
245
|
+
f"Total {MapAttribute[attribute.name].value.lower()}:",
|
|
246
|
+
html.Br(),
|
|
247
|
+
f"{summed_mass:.2f} {unit}",
|
|
248
|
+
]
|
|
249
|
+
)
|
|
250
|
+
if MapType[attribute.name].value == "MASS" and summed_mass is not None
|
|
251
|
+
else ""
|
|
252
|
+
)
|
|
253
|
+
return html.Div(
|
|
254
|
+
annotation,
|
|
255
|
+
style={
|
|
256
|
+
"position": "absolute",
|
|
257
|
+
"top": "210px",
|
|
258
|
+
"right": "4px",
|
|
259
|
+
"backgroundColor": "rgba(255,255,255,0.8)",
|
|
260
|
+
"padding": "1px 1px",
|
|
261
|
+
"fontWeight": "bold",
|
|
262
|
+
"fontSize": "15px",
|
|
263
|
+
"display": "block",
|
|
264
|
+
},
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def _create_polygon_legend(
|
|
269
|
+
options: List[str],
|
|
270
|
+
con_url: Optional[str],
|
|
271
|
+
haz_url: Optional[str], # Keep for backward compatibility
|
|
272
|
+
nogo_url: Optional[str],
|
|
273
|
+
) -> List:
|
|
274
|
+
legend: List = []
|
|
275
|
+
hide_con = con_url is None or LayoutLabels.SHOW_CONTAINMENT_POLYGON not in options
|
|
276
|
+
hide_nogo = (
|
|
277
|
+
nogo_url is None and haz_url is None
|
|
278
|
+
) or LayoutLabels.SHOW_NOGO_POLYGON not in options
|
|
279
|
+
outline = LayoutLabels.SHOW_POLYGONS_AS_OUTLINES in options
|
|
280
|
+
if hide_con and hide_nogo:
|
|
281
|
+
return legend
|
|
282
|
+
legend_items = []
|
|
283
|
+
square = {"width": "12px", "height": "12px", "marginRight": "6px"}
|
|
284
|
+
text = {"color": "black", "fontSize": "14px"}
|
|
285
|
+
if not hide_con:
|
|
286
|
+
legend_items.append(
|
|
287
|
+
html.Div(
|
|
288
|
+
style={"display": "flex", "alignItems": "center"},
|
|
289
|
+
children=[
|
|
290
|
+
html.Div(
|
|
291
|
+
style={
|
|
292
|
+
**square,
|
|
293
|
+
"backgroundColor": "transparent"
|
|
294
|
+
if outline
|
|
295
|
+
else "rgba(0, 172, 0, 0.47)",
|
|
296
|
+
"border": "3px solid rgba(0, 172, 0, 0.70)"
|
|
297
|
+
if outline
|
|
298
|
+
else "transparent",
|
|
299
|
+
}
|
|
300
|
+
),
|
|
301
|
+
html.Div("Containment Polygon", style=text),
|
|
302
|
+
],
|
|
303
|
+
)
|
|
304
|
+
)
|
|
305
|
+
if not hide_nogo:
|
|
306
|
+
legend_items.append(
|
|
307
|
+
html.Div(
|
|
308
|
+
style={"display": "flex", "alignItems": "center"},
|
|
309
|
+
children=[
|
|
310
|
+
html.Div(
|
|
311
|
+
style={
|
|
312
|
+
**square,
|
|
313
|
+
"backgroundColor": "transparent"
|
|
314
|
+
if outline
|
|
315
|
+
else "rgba(200, 0, 0, 0.47)",
|
|
316
|
+
"border": "3px solid rgba(200, 0, 0, 0.70)"
|
|
317
|
+
if outline
|
|
318
|
+
else "transparent",
|
|
319
|
+
}
|
|
320
|
+
),
|
|
321
|
+
html.Div("No-go Polygon", style=text),
|
|
322
|
+
],
|
|
323
|
+
)
|
|
324
|
+
)
|
|
325
|
+
legend.append(
|
|
326
|
+
wsc.ViewAnnotation(
|
|
327
|
+
id="polygon_legends",
|
|
328
|
+
children=html.Div(
|
|
329
|
+
children=legend_items,
|
|
330
|
+
style={
|
|
331
|
+
"position": "absolute",
|
|
332
|
+
"top": "50px",
|
|
333
|
+
"left": "4px",
|
|
334
|
+
"backgroundColor": "rgba(255,255,255,0.9)",
|
|
335
|
+
"padding": "6px 8px",
|
|
336
|
+
"borderRadius": "4px",
|
|
337
|
+
"boxShadow": "0 0 4px rgba(0,0,0,0.2)",
|
|
338
|
+
"zIndex": 10,
|
|
339
|
+
},
|
|
340
|
+
),
|
|
341
|
+
)
|
|
342
|
+
)
|
|
343
|
+
return legend
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
# pylint: disable=too-many-arguments, too-many-locals
|
|
237
347
|
def create_map_annotations(
|
|
238
348
|
formation: str,
|
|
239
349
|
surface_data: Optional[SurfaceData],
|
|
240
350
|
colortables: List[Dict[str, Any]],
|
|
241
351
|
attribute: MapAttribute,
|
|
242
352
|
unit: str,
|
|
353
|
+
current_total: Optional[float],
|
|
354
|
+
options: List[str],
|
|
355
|
+
con_url: Optional[str],
|
|
356
|
+
haz_url: Optional[str],
|
|
357
|
+
nogo_url: Optional[str],
|
|
243
358
|
) -> List[wsc.ViewAnnotation]:
|
|
244
359
|
annotations = []
|
|
245
360
|
if (
|
|
@@ -268,7 +383,9 @@ def create_map_annotations(
|
|
|
268
383
|
colorTables=colortables,
|
|
269
384
|
),
|
|
270
385
|
wsc.ViewFooter(children=formation),
|
|
271
|
-
|
|
386
|
+
_create_summed_mass_annotation(attribute, current_total, unit),
|
|
387
|
+
]
|
|
388
|
+
+ _create_polygon_legend(options, con_url, haz_url, nogo_url),
|
|
272
389
|
)
|
|
273
390
|
)
|
|
274
391
|
return annotations
|
|
@@ -286,7 +403,8 @@ def create_map_viewports() -> Dict:
|
|
|
286
403
|
"colormap-layer",
|
|
287
404
|
"fault-polygons-layer",
|
|
288
405
|
"license-boundary-layer",
|
|
289
|
-
"
|
|
406
|
+
"nogo-boundary-layer",
|
|
407
|
+
"hazardous-boundary-layer", # Keep for backward compatibility
|
|
290
408
|
"well-picks-layer",
|
|
291
409
|
"plume-polygon-layer",
|
|
292
410
|
],
|
|
@@ -302,16 +420,35 @@ def create_map_layers(
|
|
|
302
420
|
surface_data: Optional[SurfaceData],
|
|
303
421
|
fault_polygon_url: Optional[str],
|
|
304
422
|
containment_bounds_url: Optional[str],
|
|
305
|
-
|
|
423
|
+
nogo_bounds_url: Optional[str],
|
|
424
|
+
hazardous_bounds_url: Optional[str], # Keep for backward compatibility
|
|
306
425
|
well_pick_provider: Optional[EnsembleWellPicks],
|
|
307
426
|
plume_extent_data: Optional[geojson.FeatureCollection],
|
|
308
|
-
options_dialog_options: List[
|
|
427
|
+
options_dialog_options: List[str],
|
|
309
428
|
selected_wells: List[str],
|
|
429
|
+
show_contours: bool,
|
|
430
|
+
num_contours: Optional[float],
|
|
310
431
|
) -> List[Dict]:
|
|
311
432
|
layers = []
|
|
433
|
+
outline = LayoutLabels.SHOW_POLYGONS_AS_OUTLINES in options_dialog_options
|
|
312
434
|
if surface_data is not None:
|
|
313
435
|
# Update ColormapLayer
|
|
314
436
|
meta = surface_data.meta_data
|
|
437
|
+
|
|
438
|
+
# Generate contour lines
|
|
439
|
+
contours = []
|
|
440
|
+
if (
|
|
441
|
+
show_contours
|
|
442
|
+
and surface_data.color_map_range[0] is not None
|
|
443
|
+
and surface_data.color_map_range[1] is not None
|
|
444
|
+
and num_contours is not None
|
|
445
|
+
):
|
|
446
|
+
min_val, max_val = surface_data.color_map_range
|
|
447
|
+
assert min_val is not None and max_val is not None
|
|
448
|
+
buffer = 0.01 * (max_val - min_val) # Strange effects at min_val/max_val
|
|
449
|
+
step = (max_val - min_val + 2 * buffer) / (np.round(num_contours) + 1)
|
|
450
|
+
contours = [min_val + step - buffer, step]
|
|
451
|
+
|
|
315
452
|
layers.append(
|
|
316
453
|
{
|
|
317
454
|
"@@type": "MapLayer",
|
|
@@ -327,6 +464,7 @@ def create_map_layers(
|
|
|
327
464
|
"colorMapName": surface_data.color_map_name,
|
|
328
465
|
"colorMapRange": surface_data.color_map_range,
|
|
329
466
|
"material": False,
|
|
467
|
+
"contours": contours,
|
|
330
468
|
}
|
|
331
469
|
)
|
|
332
470
|
|
|
@@ -353,24 +491,52 @@ def create_map_layers(
|
|
|
353
491
|
"name": "Containment Polygon",
|
|
354
492
|
"id": "license-boundary-layer",
|
|
355
493
|
"data": containment_bounds_url,
|
|
356
|
-
"stroked":
|
|
494
|
+
"stroked": outline,
|
|
495
|
+
"filled": not outline,
|
|
357
496
|
"getFillColor": [0, 172, 0, 120],
|
|
497
|
+
"getLineColor": [0, 172, 0, 120],
|
|
498
|
+
"getLineWidth": 3,
|
|
499
|
+
"lineWidthUnits": "pixels",
|
|
500
|
+
"visible": True,
|
|
501
|
+
}
|
|
502
|
+
)
|
|
503
|
+
|
|
504
|
+
if (
|
|
505
|
+
nogo_bounds_url is not None
|
|
506
|
+
and LayoutLabels.SHOW_NOGO_POLYGON in options_dialog_options
|
|
507
|
+
):
|
|
508
|
+
layers.append(
|
|
509
|
+
{
|
|
510
|
+
"@@type": "GeoJsonLayer",
|
|
511
|
+
"name": "No-go Polygon",
|
|
512
|
+
"id": "nogo-boundary-layer",
|
|
513
|
+
"data": nogo_bounds_url,
|
|
514
|
+
"stroked": outline,
|
|
515
|
+
"filled": not outline,
|
|
516
|
+
"getFillColor": [200, 0, 0, 120],
|
|
517
|
+
"getLineColor": [200, 0, 0, 180],
|
|
518
|
+
"getLineWidth": 3,
|
|
519
|
+
"lineWidthUnits": "pixels",
|
|
358
520
|
"visible": True,
|
|
359
521
|
}
|
|
360
522
|
)
|
|
361
523
|
|
|
362
524
|
if (
|
|
363
|
-
|
|
364
|
-
and LayoutLabels.
|
|
525
|
+
hazardous_bounds_url is not None
|
|
526
|
+
and LayoutLabels.SHOW_NOGO_POLYGON in options_dialog_options
|
|
365
527
|
):
|
|
366
528
|
layers.append(
|
|
367
529
|
{
|
|
368
530
|
"@@type": "GeoJsonLayer",
|
|
369
|
-
"name": "
|
|
531
|
+
"name": "No-go Polygon",
|
|
370
532
|
"id": "hazardous-boundary-layer",
|
|
371
|
-
"data":
|
|
372
|
-
"stroked":
|
|
533
|
+
"data": hazardous_bounds_url,
|
|
534
|
+
"stroked": outline,
|
|
535
|
+
"filled": not outline,
|
|
373
536
|
"getFillColor": [200, 0, 0, 120],
|
|
537
|
+
"getLineColor": [200, 0, 0, 180],
|
|
538
|
+
"getLineWidth": 3,
|
|
539
|
+
"lineWidthUnits": "pixels",
|
|
374
540
|
"visible": True,
|
|
375
541
|
}
|
|
376
542
|
)
|
|
@@ -551,7 +717,7 @@ def process_containment_info(
|
|
|
551
717
|
mark_choice=mark_choice,
|
|
552
718
|
sorting=sorting,
|
|
553
719
|
phases=[phase for phase in menu_options["phases"] if phase != "total"],
|
|
554
|
-
containments=["
|
|
720
|
+
containments=["nogo", "outside", "contained"],
|
|
555
721
|
plume_groups=plume_groups,
|
|
556
722
|
use_stats=lines_to_show == "stat",
|
|
557
723
|
date_option=date_option,
|
|
@@ -631,20 +797,18 @@ def process_summed_mass(
|
|
|
631
797
|
datestr: Optional[str],
|
|
632
798
|
attribute: MapAttribute,
|
|
633
799
|
summed_mass: Optional[float],
|
|
634
|
-
surf_data: Optional[SurfaceData],
|
|
635
800
|
summed_co2: Dict[str, float],
|
|
636
801
|
unit: str,
|
|
637
|
-
) -> Tuple[Optional[
|
|
802
|
+
) -> Tuple[Optional[float], Dict[str, float]]:
|
|
638
803
|
summed_co2_key = f"{formation}-{realization[0]}-{datestr}-{attribute}-{unit}"
|
|
804
|
+
current_total = None
|
|
639
805
|
if len(realization) == 1:
|
|
640
806
|
if MapType[MapAttribute(attribute).name].value == "MASS":
|
|
641
807
|
if summed_mass is not None and summed_co2_key not in summed_co2:
|
|
642
808
|
summed_co2[summed_co2_key] = summed_mass
|
|
643
|
-
if summed_co2_key in summed_co2
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
)
|
|
647
|
-
return surf_data, summed_co2
|
|
809
|
+
if summed_co2_key in summed_co2:
|
|
810
|
+
current_total = summed_co2[summed_co2_key]
|
|
811
|
+
return current_total, summed_co2
|
|
648
812
|
|
|
649
813
|
|
|
650
814
|
def export_figure_data_to_csv(
|
|
@@ -11,7 +11,6 @@ import pandas as pd
|
|
|
11
11
|
import plotly.express as px
|
|
12
12
|
import plotly.graph_objects as go
|
|
13
13
|
|
|
14
|
-
from webviz_subsurface._providers import EnsembleTableProvider
|
|
15
14
|
from webviz_subsurface._utils.enum_shim import StrEnum
|
|
16
15
|
from webviz_subsurface.plugins._co2_migration._utilities.containment_data_provider import (
|
|
17
16
|
ContainmentDataProvider,
|
|
@@ -32,19 +31,6 @@ class _Columns(StrEnum):
|
|
|
32
31
|
VOLUME_OUTSIDE = "volume_outside"
|
|
33
32
|
|
|
34
33
|
|
|
35
|
-
class Colors(StrEnum):
|
|
36
|
-
# pylint: disable=invalid-name
|
|
37
|
-
total = "#222222"
|
|
38
|
-
contained = "#00aa00"
|
|
39
|
-
outside = "#006ddd"
|
|
40
|
-
hazardous = "#dd4300"
|
|
41
|
-
dissolved_water = "#208eb7"
|
|
42
|
-
dissolved_oil = "#A0522D"
|
|
43
|
-
gas = "#C41E3A"
|
|
44
|
-
free_gas = "#FF2400"
|
|
45
|
-
trapped_gas = "#880808"
|
|
46
|
-
|
|
47
|
-
|
|
48
34
|
class Marks(StrEnum):
|
|
49
35
|
dissolved_water = "/"
|
|
50
36
|
dissolved_oil = "x"
|
|
@@ -61,61 +47,76 @@ class Lines(StrEnum):
|
|
|
61
47
|
trapped_gas = "dashdot"
|
|
62
48
|
|
|
63
49
|
|
|
64
|
-
|
|
65
|
-
"#
|
|
66
|
-
"#
|
|
67
|
-
"#
|
|
68
|
-
"#
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"#
|
|
74
|
-
"#
|
|
75
|
-
"#
|
|
76
|
-
"#
|
|
50
|
+
_CONTAINMENT_COLORS = {
|
|
51
|
+
"total": ("#222222", "#909090"),
|
|
52
|
+
"contained": ("#00aa00", "#55ff55"),
|
|
53
|
+
"outside": ("#006ddd", "#6eb6ff"),
|
|
54
|
+
"nogo": ("#dd4300", "#ff9a6e"),
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
_PHASE_COLORS = {
|
|
59
|
+
"total": ("#222222", "#909090"),
|
|
60
|
+
"dissolved_water": ("#208eb7", "#81cde9"),
|
|
61
|
+
"dissolved_oil": ("#A0522D", "#C28163"),
|
|
62
|
+
"gas": ("#C41E3A", "#E42E5A"),
|
|
63
|
+
"free_gas": ("#FF2400", "#FF7430"),
|
|
64
|
+
"trapped_gas": ("#880808", "#C84848"),
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
_GENERAL_COLORS = [
|
|
69
|
+
("#e91451", "#f589a8"),
|
|
70
|
+
("#daa218", "#f2d386"),
|
|
71
|
+
("#208eb7", "#81cde9"),
|
|
72
|
+
("#84bc04", "#cdfc63"),
|
|
73
|
+
("#b74532", "#e19e92"),
|
|
74
|
+
("#9a89b4", "#ccc4d9"),
|
|
75
|
+
("#8d30ba", "#c891e3"),
|
|
76
|
+
("#256b33", "#77d089"),
|
|
77
|
+
("#95704d", "#cfb7a1"),
|
|
78
|
+
("#1357ca", "#7ba7f3"),
|
|
79
|
+
("#f75ef0", "#fbaef7"),
|
|
80
|
+
("#34b36f", "#93e0b7"),
|
|
77
81
|
]
|
|
78
82
|
|
|
83
|
+
|
|
79
84
|
_LIGHTER_COLORS = {
|
|
80
85
|
"black": "#909090",
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"#dd4300": "#ff9a6e",
|
|
85
|
-
"#e91451": "#f589a8",
|
|
86
|
-
"#daa218": "#f2d386",
|
|
87
|
-
"#208eb7": "#81cde9",
|
|
88
|
-
"#84bc04": "#cdfc63",
|
|
89
|
-
"#b74532": "#e19e92",
|
|
90
|
-
"#9a89b4": "#ccc4d9",
|
|
91
|
-
"#8d30ba": "#c891e3",
|
|
92
|
-
"#256b33": "#77d089",
|
|
93
|
-
"#95704d": "#cfb7a1",
|
|
94
|
-
"#1357ca": "#7ba7f3",
|
|
95
|
-
"#f75ef0": "#fbaef7",
|
|
96
|
-
"#34b36f": "#93e0b7",
|
|
97
|
-
"#C41E3A": "#E42E5A",
|
|
98
|
-
"#FF2400": "#FF7430",
|
|
99
|
-
"#880808": "#C84848",
|
|
86
|
+
**dict(_CONTAINMENT_COLORS.values()),
|
|
87
|
+
**dict(_PHASE_COLORS.values()),
|
|
88
|
+
**dict(_GENERAL_COLORS),
|
|
100
89
|
}
|
|
101
90
|
|
|
91
|
+
_LABEL_TRANSLATIONS = {
|
|
92
|
+
"nogo": "no-go",
|
|
93
|
+
"dissolved_water": "dissolved water",
|
|
94
|
+
"dissolved_oil": "dissolved oil",
|
|
95
|
+
"free_gas": "free gas",
|
|
96
|
+
"trapped_gas": "trapped gas",
|
|
97
|
+
}
|
|
102
98
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return
|
|
111
|
-
|
|
112
|
-
|
|
99
|
+
|
|
100
|
+
def _translate_labels(df: Union[pd.DataFrame, Dict], column: str = "type") -> None:
|
|
101
|
+
def translate_label(label: str) -> str:
|
|
102
|
+
if ", " in label:
|
|
103
|
+
parts = label.split(", ")
|
|
104
|
+
translated_parts = [_LABEL_TRANSLATIONS.get(part, part) for part in parts]
|
|
105
|
+
return ", ".join(translated_parts)
|
|
106
|
+
return _LABEL_TRANSLATIONS.get(label, label)
|
|
107
|
+
|
|
108
|
+
if isinstance(df, dict):
|
|
109
|
+
df[column] = [translate_label(label) for label in df[column]]
|
|
110
|
+
else:
|
|
111
|
+
df[column] = df[column].apply(translate_label)
|
|
113
112
|
|
|
114
113
|
|
|
115
114
|
def _get_colors(color_options: List[str], split: str) -> List[str]:
|
|
116
|
-
if split
|
|
117
|
-
return [
|
|
118
|
-
|
|
115
|
+
if split == "containment":
|
|
116
|
+
return [_CONTAINMENT_COLORS[option][0] for option in color_options]
|
|
117
|
+
if split == "phase":
|
|
118
|
+
return [_PHASE_COLORS[option][0] for option in color_options]
|
|
119
|
+
options = [x[0] for x in _GENERAL_COLORS]
|
|
119
120
|
if split == "region":
|
|
120
121
|
options.reverse()
|
|
121
122
|
num_cols = len(color_options)
|
|
@@ -268,8 +269,8 @@ def _prepare_pattern_and_color_options_statistics_plot(
|
|
|
268
269
|
|
|
269
270
|
|
|
270
271
|
def _find_default_legendonly(df: pd.DataFrame, categories: List[str]) -> List[str]:
|
|
271
|
-
if "
|
|
272
|
-
default_option = "
|
|
272
|
+
if "no-go" in categories:
|
|
273
|
+
default_option = "no-go"
|
|
273
274
|
else:
|
|
274
275
|
max_value = -999.9
|
|
275
276
|
default_option = categories[0]
|
|
@@ -416,7 +417,7 @@ def _add_sort_key_and_real(
|
|
|
416
417
|
sort_value = np.sum(
|
|
417
418
|
df[
|
|
418
419
|
(df["phase"] == "total")
|
|
419
|
-
& (df["containment"] == "
|
|
420
|
+
& (df["containment"] == "nogo")
|
|
420
421
|
& (df["zone"] == containment_info.zone)
|
|
421
422
|
& (df["region"] == containment_info.region)
|
|
422
423
|
& (df["plume_group"] == containment_info.plume_group)
|
|
@@ -530,6 +531,9 @@ def generate_co2_volume_figure(
|
|
|
530
531
|
color_choice,
|
|
531
532
|
mark_choice,
|
|
532
533
|
)
|
|
534
|
+
_translate_labels(df, "type")
|
|
535
|
+
_translate_labels(cat_ord, "type")
|
|
536
|
+
|
|
533
537
|
fig = px.bar(
|
|
534
538
|
df,
|
|
535
539
|
y="real",
|
|
@@ -590,6 +594,9 @@ def generate_co2_time_containment_one_realization_figure(
|
|
|
590
594
|
color_choice,
|
|
591
595
|
mark_choice,
|
|
592
596
|
)
|
|
597
|
+
_translate_labels(df, "type")
|
|
598
|
+
_translate_labels(cat_ord, "type")
|
|
599
|
+
|
|
593
600
|
fig = px.area(
|
|
594
601
|
df,
|
|
595
602
|
x="date",
|
|
@@ -776,6 +783,8 @@ def generate_co2_time_containment_figure(
|
|
|
776
783
|
options = _prepare_line_type_and_color_options(
|
|
777
784
|
df, containment_info, color_choice, mark_choice
|
|
778
785
|
)
|
|
786
|
+
_translate_labels(df, "name")
|
|
787
|
+
_translate_labels(options, "name")
|
|
779
788
|
if legendonly_traces is None:
|
|
780
789
|
inactive_cols_at_startup = list(
|
|
781
790
|
options[~(options["line_type"].isin(["solid", "0px"]))]["name"]
|
|
@@ -788,6 +797,14 @@ def generate_co2_time_containment_figure(
|
|
|
788
797
|
except ValueError:
|
|
789
798
|
pass
|
|
790
799
|
|
|
800
|
+
options["name"] = options["name"].apply(
|
|
801
|
+
lambda label: ", ".join(
|
|
802
|
+
[_LABEL_TRANSLATIONS.get(part, part) for part in label.split(", ")]
|
|
803
|
+
)
|
|
804
|
+
if ", " in label
|
|
805
|
+
else _LABEL_TRANSLATIONS.get(label, label)
|
|
806
|
+
)
|
|
807
|
+
|
|
791
808
|
fig = go.Figure()
|
|
792
809
|
# Generate dummy scatters for legend entries
|
|
793
810
|
dummy_args = {"x": df["date"], "mode": "lines", "hoverinfo": "none"}
|
|
@@ -907,6 +924,8 @@ def generate_co2_statistics_figure(
|
|
|
907
924
|
color_choice,
|
|
908
925
|
mark_choice,
|
|
909
926
|
)
|
|
927
|
+
_translate_labels(df, "type")
|
|
928
|
+
_translate_labels(cat_ord, "type")
|
|
910
929
|
|
|
911
930
|
df = df.drop(columns=["REAL"]).reset_index(drop=True)
|
|
912
931
|
fig = px.ecdf(
|
|
@@ -973,6 +992,8 @@ def generate_co2_box_plot_figure(
|
|
|
973
992
|
color_choice,
|
|
974
993
|
mark_choice,
|
|
975
994
|
)
|
|
995
|
+
_translate_labels(df, "type")
|
|
996
|
+
_translate_labels(cat_ord, "type")
|
|
976
997
|
|
|
977
998
|
fig = go.Figure()
|
|
978
999
|
for count, type_val in enumerate(cat_ord["type"], 0):
|