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
|
@@ -25,6 +25,9 @@ class TornadoData:
|
|
|
25
25
|
self._cut_sensitivities_by_ref()
|
|
26
26
|
self._sort_sensitivities_by_max()
|
|
27
27
|
self._real_df = self._create_real_df(dframe)
|
|
28
|
+
self.mean_per_mc_sens = (
|
|
29
|
+
dframe[dframe["SENSTYPE"] == "mc"].groupby("SENSNAME")["VALUE"].mean()
|
|
30
|
+
)
|
|
28
31
|
|
|
29
32
|
def _validate_input(self, dframe: pd.DataFrame) -> None:
|
|
30
33
|
for col in self.REQUIRED_COLUMNS:
|
|
@@ -3,16 +3,15 @@ import io
|
|
|
3
3
|
import json
|
|
4
4
|
import logging
|
|
5
5
|
import math
|
|
6
|
+
import tempfile
|
|
6
7
|
from dataclasses import asdict, dataclass
|
|
7
8
|
from typing import Any, List, Optional, Tuple, Union
|
|
8
9
|
from urllib.parse import quote
|
|
9
|
-
from uuid import uuid4
|
|
10
10
|
|
|
11
11
|
import flask
|
|
12
12
|
import flask_caching
|
|
13
13
|
import xtgeo
|
|
14
14
|
from dash import Dash
|
|
15
|
-
from webviz_config.webviz_instance_info import WEBVIZ_INSTANCE_INFO
|
|
16
15
|
|
|
17
16
|
from webviz_subsurface._utils.perf_timer import PerfTimer
|
|
18
17
|
|
|
@@ -46,17 +45,13 @@ class SurfaceImageMeta:
|
|
|
46
45
|
|
|
47
46
|
class SurfaceImageServer:
|
|
48
47
|
def __init__(self, app: Dash) -> None:
|
|
49
|
-
cache_dir = (
|
|
50
|
-
WEBVIZ_INSTANCE_INFO.storage_folder
|
|
51
|
-
/ f"SurfaceImageServer_filecache_{uuid4()}"
|
|
52
|
-
)
|
|
48
|
+
cache_dir = tempfile.mkdtemp()
|
|
53
49
|
LOGGER.debug(f"Setting up file cache in: {cache_dir}")
|
|
54
50
|
self._image_cache = flask_caching.Cache(
|
|
55
51
|
config={
|
|
56
52
|
"CACHE_TYPE": "FileSystemCache",
|
|
57
53
|
"CACHE_DIR": cache_dir,
|
|
58
54
|
"CACHE_DEFAULT_TIMEOUT": 0,
|
|
59
|
-
"CACHE_OPTIONS": {"mode": 0o660},
|
|
60
55
|
}
|
|
61
56
|
)
|
|
62
57
|
self._image_cache.init_app(app.server)
|
|
@@ -22,6 +22,7 @@ from webviz_subsurface.plugins._co2_leakage._utilities.callbacks import (
|
|
|
22
22
|
process_visualization_info,
|
|
23
23
|
property_origin,
|
|
24
24
|
readable_name,
|
|
25
|
+
set_plot_ids,
|
|
25
26
|
)
|
|
26
27
|
from webviz_subsurface.plugins._co2_leakage._utilities.fault_polygons import (
|
|
27
28
|
FaultPolygonsHandler,
|
|
@@ -34,10 +35,10 @@ from webviz_subsurface.plugins._co2_leakage._utilities.generic import (
|
|
|
34
35
|
)
|
|
35
36
|
from webviz_subsurface.plugins._co2_leakage._utilities.initialization import (
|
|
36
37
|
init_map_attribute_names,
|
|
38
|
+
init_menu_options,
|
|
37
39
|
init_surface_providers,
|
|
38
40
|
init_table_provider,
|
|
39
41
|
init_well_pick_provider,
|
|
40
|
-
init_zone_and_region_options,
|
|
41
42
|
process_files,
|
|
42
43
|
)
|
|
43
44
|
from webviz_subsurface.plugins._co2_leakage.views.mainview.mainview import (
|
|
@@ -165,12 +166,13 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
165
166
|
well_pick_dict,
|
|
166
167
|
map_surface_names_to_well_pick_names,
|
|
167
168
|
)
|
|
168
|
-
#
|
|
169
|
-
self.
|
|
169
|
+
# Phase (in case of residual trapping), zone and region options
|
|
170
|
+
self._menu_options = init_menu_options(
|
|
170
171
|
ensemble_paths,
|
|
171
172
|
self._co2_table_providers,
|
|
172
173
|
self._co2_actual_volume_table_providers,
|
|
173
|
-
|
|
174
|
+
plume_mass_relpath,
|
|
175
|
+
plume_actual_volume_relpath,
|
|
174
176
|
)
|
|
175
177
|
except Exception as err:
|
|
176
178
|
self._error_message = f"Plugin initialization failed: {err}"
|
|
@@ -196,7 +198,7 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
196
198
|
self._map_attribute_names,
|
|
197
199
|
[c["name"] for c in self._color_tables], # type: ignore
|
|
198
200
|
self._well_pick_names,
|
|
199
|
-
self.
|
|
201
|
+
self._menu_options,
|
|
200
202
|
),
|
|
201
203
|
self.Ids.MAIN_SETTINGS,
|
|
202
204
|
)
|
|
@@ -229,25 +231,18 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
229
231
|
raise ValueError(f"Failed to fetch dates for attribute '{att_name}'")
|
|
230
232
|
return dates
|
|
231
233
|
|
|
234
|
+
# Might want to do some refactoring if this gets too big
|
|
235
|
+
# pylint: disable=too-many-statements
|
|
232
236
|
def _set_callbacks(self) -> None:
|
|
233
237
|
# Cannot avoid many arguments since all the parameters are needed
|
|
234
238
|
# to determine what to plot
|
|
235
239
|
# pylint: disable=too-many-arguments
|
|
236
|
-
# pylint: disable=too-many-locals
|
|
237
240
|
@callback(
|
|
238
|
-
Output(
|
|
239
|
-
self._settings_component(ViewSettings.Ids.CONTAINMENT_VIEW), "value"
|
|
240
|
-
),
|
|
241
241
|
Output(self._view_component(MapViewElement.Ids.BAR_PLOT), "figure"),
|
|
242
242
|
Output(self._view_component(MapViewElement.Ids.TIME_PLOT), "figure"),
|
|
243
243
|
Output(
|
|
244
244
|
self._view_component(MapViewElement.Ids.TIME_PLOT_ONE_REAL), "figure"
|
|
245
245
|
),
|
|
246
|
-
Output(self._view_component(MapViewElement.Ids.BAR_PLOT), "style"),
|
|
247
|
-
Output(self._view_component(MapViewElement.Ids.TIME_PLOT), "style"),
|
|
248
|
-
Output(
|
|
249
|
-
self._view_component(MapViewElement.Ids.TIME_PLOT_ONE_REAL), "style"
|
|
250
|
-
),
|
|
251
246
|
Input(self._settings_component(ViewSettings.Ids.ENSEMBLE), "value"),
|
|
252
247
|
Input(self._settings_component(ViewSettings.Ids.GRAPH_SOURCE), "value"),
|
|
253
248
|
Input(self._settings_component(ViewSettings.Ids.CO2_SCALE), "value"),
|
|
@@ -258,7 +253,11 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
258
253
|
Input(self._settings_component(ViewSettings.Ids.Y_MAX_GRAPH), "value"),
|
|
259
254
|
Input(self._settings_component(ViewSettings.Ids.ZONE), "value"),
|
|
260
255
|
Input(self._settings_component(ViewSettings.Ids.REGION), "value"),
|
|
261
|
-
Input(self._settings_component(ViewSettings.Ids.
|
|
256
|
+
Input(self._settings_component(ViewSettings.Ids.PHASE), "value"),
|
|
257
|
+
Input(self._settings_component(ViewSettings.Ids.CONTAINMENT), "value"),
|
|
258
|
+
Input(self._settings_component(ViewSettings.Ids.COLOR_BY), "value"),
|
|
259
|
+
Input(self._settings_component(ViewSettings.Ids.MARK_BY), "value"),
|
|
260
|
+
Input(self._settings_component(ViewSettings.Ids.SORT_PLOT), "value"),
|
|
262
261
|
)
|
|
263
262
|
@callback_typecheck
|
|
264
263
|
def update_graphs(
|
|
@@ -272,15 +271,23 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
272
271
|
y_max_val: Optional[float],
|
|
273
272
|
zone: Optional[str],
|
|
274
273
|
region: Optional[str],
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
274
|
+
phase: str,
|
|
275
|
+
containment: str,
|
|
276
|
+
color_choice: str,
|
|
277
|
+
mark_choice: Optional[str],
|
|
278
|
+
sorting: str,
|
|
279
|
+
) -> Tuple[Dict, go.Figure, go.Figure, go.Figure]:
|
|
280
|
+
# pylint: disable=too-many-locals
|
|
281
|
+
figs = [no_update] * 3
|
|
278
282
|
cont_info = process_containment_info(
|
|
279
283
|
zone,
|
|
280
284
|
region,
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
285
|
+
phase,
|
|
286
|
+
containment,
|
|
287
|
+
color_choice,
|
|
288
|
+
mark_choice,
|
|
289
|
+
sorting,
|
|
290
|
+
self._menu_options[ensemble][source],
|
|
284
291
|
)
|
|
285
292
|
if source in [
|
|
286
293
|
GraphSource.CONTAINMENT_MASS,
|
|
@@ -290,12 +297,11 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
290
297
|
y_min_val if len(y_min_auto) == 0 else None,
|
|
291
298
|
y_max_val if len(y_max_auto) == 0 else None,
|
|
292
299
|
]
|
|
293
|
-
out["styles"] = [{}] * 3
|
|
294
300
|
if (
|
|
295
301
|
source == GraphSource.CONTAINMENT_MASS
|
|
296
302
|
and ensemble in self._co2_table_providers
|
|
297
303
|
):
|
|
298
|
-
|
|
304
|
+
figs[: len(figs)] = generate_containment_figures(
|
|
299
305
|
self._co2_table_providers[ensemble],
|
|
300
306
|
co2_scale,
|
|
301
307
|
realizations[0],
|
|
@@ -306,18 +312,14 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
306
312
|
source == GraphSource.CONTAINMENT_ACTUAL_VOLUME
|
|
307
313
|
and ensemble in self._co2_actual_volume_table_providers
|
|
308
314
|
):
|
|
309
|
-
|
|
315
|
+
figs[: len(figs)] = generate_containment_figures(
|
|
310
316
|
self._co2_actual_volume_table_providers[ensemble],
|
|
311
317
|
co2_scale,
|
|
312
318
|
realizations[0],
|
|
313
319
|
y_limits,
|
|
314
320
|
cont_info,
|
|
315
321
|
)
|
|
316
|
-
|
|
317
|
-
fig["layout"][
|
|
318
|
-
"uirevision"
|
|
319
|
-
] = f"{source}-{co2_scale}-{cont_info['zone']}-{cont_info['region']}"
|
|
320
|
-
out["figs"][-1]["layout"]["uirevision"] += f"-{realizations}"
|
|
322
|
+
set_plot_ids(figs, source, co2_scale, cont_info, realizations)
|
|
321
323
|
elif source == GraphSource.UNSMRY:
|
|
322
324
|
if self._unsmry_providers is not None:
|
|
323
325
|
if ensemble in self._unsmry_providers:
|
|
@@ -326,14 +328,13 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
326
328
|
co2_scale,
|
|
327
329
|
self._co2_table_providers[ensemble],
|
|
328
330
|
)
|
|
329
|
-
|
|
330
|
-
out["styles"][: len(u_figs)] = [{}] * len(u_figs)
|
|
331
|
+
figs = list(u_figs)
|
|
331
332
|
else:
|
|
332
333
|
LOGGER.warning(
|
|
333
334
|
"""UNSMRY file has not been specified as input.
|
|
334
335
|
Please use unsmry_relpath in the configuration."""
|
|
335
336
|
)
|
|
336
|
-
return
|
|
337
|
+
return figs # type: ignore
|
|
337
338
|
|
|
338
339
|
@callback(
|
|
339
340
|
Output(self._view_component(MapViewElement.Ids.DATE_SLIDER), "marks"),
|
|
@@ -352,15 +353,17 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
352
353
|
}
|
|
353
354
|
for i, d in enumerate(date_list)
|
|
354
355
|
}
|
|
355
|
-
|
|
356
|
-
return dates, initial_date
|
|
356
|
+
return dates, max(dates.keys())
|
|
357
357
|
|
|
358
358
|
@callback(
|
|
359
359
|
Output(self._view_component(MapViewElement.Ids.DATE_WRAPPER), "style"),
|
|
360
360
|
Input(self._settings_component(ViewSettings.Ids.PROPERTY), "value"),
|
|
361
361
|
)
|
|
362
362
|
def toggle_date_slider(attribute: str) -> Dict[str, str]:
|
|
363
|
-
if MapAttribute(attribute)
|
|
363
|
+
if MapAttribute(attribute) in [
|
|
364
|
+
MapAttribute.MIGRATION_TIME_SGAS,
|
|
365
|
+
MapAttribute.MIGRATION_TIME_AMFG,
|
|
366
|
+
]:
|
|
364
367
|
return {"display": "none"}
|
|
365
368
|
return {}
|
|
366
369
|
|
|
@@ -401,7 +404,7 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
401
404
|
)
|
|
402
405
|
|
|
403
406
|
# Cannot avoid many arguments and/or locals since all layers of the DeckGL map
|
|
404
|
-
#
|
|
407
|
+
# need to be updated simultaneously
|
|
405
408
|
# pylint: disable=too-many-arguments,too-many-locals
|
|
406
409
|
@callback(
|
|
407
410
|
Output(self._view_component(MapViewElement.Ids.DECKGL_MAP), "layers"),
|
|
@@ -512,7 +515,6 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
512
515
|
self._summed_co2,
|
|
513
516
|
self._visualization_info["unit"],
|
|
514
517
|
)
|
|
515
|
-
# Plume polygon
|
|
516
518
|
plume_polygon = None
|
|
517
519
|
if contour_data is not None:
|
|
518
520
|
plume_polygon = get_plume_polygon(
|
|
@@ -566,3 +568,43 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
566
568
|
if _n_clicks is not None:
|
|
567
569
|
return _n_clicks > 0
|
|
568
570
|
raise PreventUpdate
|
|
571
|
+
|
|
572
|
+
@callback(
|
|
573
|
+
Output(self._view_component(MapViewElement.Ids.TOP_ELEMENT), "style"),
|
|
574
|
+
Output(self._view_component(MapViewElement.Ids.BOTTOM_ELEMENT), "style"),
|
|
575
|
+
Output(self._view_component(MapViewElement.Ids.BAR_PLOT), "style"),
|
|
576
|
+
Output(self._view_component(MapViewElement.Ids.TIME_PLOT), "style"),
|
|
577
|
+
Output(
|
|
578
|
+
self._view_component(MapViewElement.Ids.TIME_PLOT_ONE_REAL), "style"
|
|
579
|
+
),
|
|
580
|
+
Input(self._settings_component(ViewSettings.Ids.ENSEMBLE), "value"),
|
|
581
|
+
Input(self._view_component(MapViewElement.Ids.SIZE_SLIDER), "value"),
|
|
582
|
+
State(self._view_component(MapViewElement.Ids.TOP_ELEMENT), "style"),
|
|
583
|
+
State(self._view_component(MapViewElement.Ids.BOTTOM_ELEMENT), "style"),
|
|
584
|
+
Input(self._settings_component(ViewSettings.Ids.GRAPH_SOURCE), "value"),
|
|
585
|
+
)
|
|
586
|
+
def resize_plots(
|
|
587
|
+
ensemble: str,
|
|
588
|
+
slider_value: float,
|
|
589
|
+
top_style: Dict,
|
|
590
|
+
bottom_style: Dict,
|
|
591
|
+
source: GraphSource,
|
|
592
|
+
) -> List[Dict]:
|
|
593
|
+
bottom_style["height"] = f"{slider_value}vh"
|
|
594
|
+
top_style["height"] = f"{80 - slider_value}vh"
|
|
595
|
+
|
|
596
|
+
styles = [{"height": f"{slider_value * 0.9 - 4}vh", "width": "90%"}] * 3
|
|
597
|
+
if source == GraphSource.UNSMRY and self._unsmry_providers is None:
|
|
598
|
+
styles = [{"display": "none"}] * 3
|
|
599
|
+
elif (
|
|
600
|
+
source == GraphSource.CONTAINMENT_MASS
|
|
601
|
+
and ensemble not in self._co2_table_providers
|
|
602
|
+
):
|
|
603
|
+
styles = [{"display": "none"}] * 3
|
|
604
|
+
elif (
|
|
605
|
+
source == GraphSource.CONTAINMENT_ACTUAL_VOLUME
|
|
606
|
+
and ensemble not in self._co2_actual_volume_table_providers
|
|
607
|
+
):
|
|
608
|
+
styles = [{"display": "none"}] * 3
|
|
609
|
+
|
|
610
|
+
return [top_style, bottom_style] + styles
|
|
@@ -6,6 +6,7 @@ import geojson
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
import plotly.graph_objects as go
|
|
8
8
|
import webviz_subsurface_components as wsc
|
|
9
|
+
from dash import no_update
|
|
9
10
|
from flask_caching import Cache
|
|
10
11
|
|
|
11
12
|
from webviz_subsurface._providers import (
|
|
@@ -30,7 +31,6 @@ from webviz_subsurface.plugins._co2_leakage._utilities.co2volume import (
|
|
|
30
31
|
from webviz_subsurface.plugins._co2_leakage._utilities.generic import (
|
|
31
32
|
Co2MassScale,
|
|
32
33
|
Co2VolumeScale,
|
|
33
|
-
ContainmentViews,
|
|
34
34
|
GraphSource,
|
|
35
35
|
LayoutLabels,
|
|
36
36
|
MapAttribute,
|
|
@@ -56,7 +56,7 @@ def property_origin(
|
|
|
56
56
|
return map_attribute_names[MapAttribute.MAX_SGAS]
|
|
57
57
|
if attribute == MapAttribute.AMFG_PLUME:
|
|
58
58
|
return map_attribute_names[MapAttribute.MAX_AMFG]
|
|
59
|
-
raise AssertionError(f"
|
|
59
|
+
raise AssertionError(f"Map attribute name not found for property: {attribute}")
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
@dataclass
|
|
@@ -86,7 +86,9 @@ class SurfaceData:
|
|
|
86
86
|
visualization_info,
|
|
87
87
|
map_attribute_names,
|
|
88
88
|
)
|
|
89
|
-
|
|
89
|
+
if surf_meta is None: # Surface file does not exist
|
|
90
|
+
return None, None
|
|
91
|
+
assert isinstance(img_url, str)
|
|
90
92
|
value_range = (
|
|
91
93
|
0.0 if np.ma.is_masked(surf_meta.val_min) else surf_meta.val_min,
|
|
92
94
|
0.0 if np.ma.is_masked(surf_meta.val_max) else surf_meta.val_max,
|
|
@@ -132,7 +134,15 @@ def derive_surface_address(
|
|
|
132
134
|
threshold=contour_data["threshold"] if contour_data else 0.0,
|
|
133
135
|
smoothing=contour_data["smoothing"] if contour_data else 0.0,
|
|
134
136
|
)
|
|
135
|
-
date =
|
|
137
|
+
date = (
|
|
138
|
+
None
|
|
139
|
+
if attribute
|
|
140
|
+
in [
|
|
141
|
+
MapAttribute.MIGRATION_TIME_SGAS,
|
|
142
|
+
MapAttribute.MIGRATION_TIME_AMFG,
|
|
143
|
+
]
|
|
144
|
+
else date
|
|
145
|
+
)
|
|
136
146
|
if len(realization) == 1:
|
|
137
147
|
return SimulatedSurfaceAddress(
|
|
138
148
|
attribute=map_attribute_names[attribute],
|
|
@@ -151,7 +161,10 @@ def derive_surface_address(
|
|
|
151
161
|
|
|
152
162
|
def readable_name(attribute: MapAttribute) -> str:
|
|
153
163
|
unit = ""
|
|
154
|
-
if attribute
|
|
164
|
+
if attribute in [
|
|
165
|
+
MapAttribute.MIGRATION_TIME_SGAS,
|
|
166
|
+
MapAttribute.MIGRATION_TIME_AMFG,
|
|
167
|
+
]:
|
|
155
168
|
unit = " [year]"
|
|
156
169
|
elif attribute in (MapAttribute.AMFG_PLUME, MapAttribute.SGAS_PLUME):
|
|
157
170
|
unit = " [# real.]"
|
|
@@ -198,7 +211,10 @@ def get_plume_polygon(
|
|
|
198
211
|
|
|
199
212
|
|
|
200
213
|
def _find_legend_title(attribute: MapAttribute, unit: str) -> str:
|
|
201
|
-
if attribute
|
|
214
|
+
if attribute in [
|
|
215
|
+
MapAttribute.MIGRATION_TIME_SGAS,
|
|
216
|
+
MapAttribute.MIGRATION_TIME_AMFG,
|
|
217
|
+
]:
|
|
202
218
|
return "years"
|
|
203
219
|
if attribute in [MapAttribute.MASS, MapAttribute.DISSOLVED, MapAttribute.FREE]:
|
|
204
220
|
return unit
|
|
@@ -213,7 +229,13 @@ def create_map_annotations(
|
|
|
213
229
|
unit: str,
|
|
214
230
|
) -> List[wsc.ViewAnnotation]:
|
|
215
231
|
annotations = []
|
|
216
|
-
if
|
|
232
|
+
if (
|
|
233
|
+
surface_data is not None
|
|
234
|
+
and surface_data.color_map_range[0] is not None
|
|
235
|
+
and surface_data.color_map_range[1] is not None
|
|
236
|
+
):
|
|
237
|
+
num_digits = np.ceil(np.log(surface_data.color_map_range[1]) / np.log(10))
|
|
238
|
+
numbersize = max((6, min((17 - num_digits, 11))))
|
|
217
239
|
annotations.append(
|
|
218
240
|
wsc.ViewAnnotation(
|
|
219
241
|
id="1_view",
|
|
@@ -227,6 +249,8 @@ def create_map_annotations(
|
|
|
227
249
|
openColorSelector=False,
|
|
228
250
|
legendScaleSize=0.1,
|
|
229
251
|
legendFontSize=20,
|
|
252
|
+
tickFontSize=numbersize,
|
|
253
|
+
numberOfTicks=2,
|
|
230
254
|
colorTables=colortables,
|
|
231
255
|
),
|
|
232
256
|
wsc.ViewFooter(children=formation),
|
|
@@ -383,7 +407,7 @@ def generate_containment_figures(
|
|
|
383
407
|
co2_scale: Union[Co2MassScale, Co2VolumeScale],
|
|
384
408
|
realization: int,
|
|
385
409
|
y_limits: List[Optional[float]],
|
|
386
|
-
containment_info: Dict[str, Union[str, None, List[str]]],
|
|
410
|
+
containment_info: Dict[str, Union[str, None, List[str], int]],
|
|
387
411
|
) -> Tuple[go.Figure, go.Figure, go.Figure]:
|
|
388
412
|
try:
|
|
389
413
|
fig0 = generate_co2_volume_figure(
|
|
@@ -484,36 +508,73 @@ def process_visualization_info(
|
|
|
484
508
|
def process_containment_info(
|
|
485
509
|
zone: Optional[str],
|
|
486
510
|
region: Optional[str],
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
]
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
511
|
+
phase: str,
|
|
512
|
+
containment: str,
|
|
513
|
+
color_choice: str,
|
|
514
|
+
mark_choice: Optional[str],
|
|
515
|
+
sorting: str,
|
|
516
|
+
menu_options: Dict[str, List[str]],
|
|
517
|
+
) -> Dict[str, Union[str, None, List[str], int]]:
|
|
518
|
+
if mark_choice is None:
|
|
519
|
+
mark_choice = "phase"
|
|
520
|
+
zones = menu_options["zones"]
|
|
521
|
+
regions = menu_options["regions"]
|
|
522
|
+
if len(zones) > 0:
|
|
523
|
+
zones = [zone_name for zone_name in zones if zone_name != "all"]
|
|
524
|
+
if len(regions) > 0:
|
|
525
|
+
regions = [reg_name for reg_name in regions if reg_name != "all"]
|
|
526
|
+
containments = ["hazardous", "outside", "contained"]
|
|
527
|
+
phases = [phase for phase in menu_options["phases"] if phase != "total"]
|
|
528
|
+
if "zone" in [mark_choice, color_choice]:
|
|
529
|
+
region = "all"
|
|
530
|
+
if "region" in [mark_choice, color_choice]:
|
|
531
|
+
zone = "all"
|
|
532
|
+
return {
|
|
533
|
+
"zone": zone,
|
|
534
|
+
"region": region,
|
|
535
|
+
"zones": zones,
|
|
536
|
+
"regions": regions,
|
|
537
|
+
"phase": phase,
|
|
538
|
+
"containment": containment,
|
|
539
|
+
"color_choice": color_choice,
|
|
540
|
+
"mark_choice": mark_choice,
|
|
541
|
+
"sorting": sorting,
|
|
542
|
+
"phases": phases,
|
|
543
|
+
"containments": containments,
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
def set_plot_ids(
|
|
548
|
+
figs: List[go.Figure],
|
|
549
|
+
source: GraphSource,
|
|
550
|
+
scale: Union[Co2MassScale, Co2VolumeScale],
|
|
551
|
+
containment_info: Dict,
|
|
552
|
+
realizations: List[int],
|
|
553
|
+
) -> None:
|
|
554
|
+
if figs[0] != no_update:
|
|
555
|
+
zone_str = (
|
|
556
|
+
containment_info["zone"] if containment_info["zone"] is not None else "None"
|
|
557
|
+
)
|
|
558
|
+
region_str = (
|
|
559
|
+
containment_info["region"]
|
|
560
|
+
if containment_info["region"] is not None
|
|
561
|
+
else "None"
|
|
562
|
+
)
|
|
563
|
+
plot_id = "-".join(
|
|
564
|
+
(
|
|
565
|
+
source,
|
|
566
|
+
scale,
|
|
567
|
+
zone_str,
|
|
568
|
+
region_str,
|
|
569
|
+
str(containment_info["phase"]),
|
|
570
|
+
str(containment_info["containment"]),
|
|
571
|
+
containment_info["color_choice"],
|
|
572
|
+
containment_info["mark_choice"],
|
|
573
|
+
)
|
|
574
|
+
)
|
|
575
|
+
for fig in figs:
|
|
576
|
+
fig["layout"]["uirevision"] = plot_id
|
|
577
|
+
figs[-1]["layout"]["uirevision"] += f"-{realizations}"
|
|
517
578
|
|
|
518
579
|
|
|
519
580
|
def process_summed_mass(
|