webviz-subsurface 0.2.36__py3-none-any.whl → 0.2.37__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/__init__.py +1 -1
- webviz_subsurface/_components/color_picker.py +1 -1
- webviz_subsurface/_providers/ensemble_polygon_provider/__init__.py +3 -0
- webviz_subsurface/_providers/ensemble_polygon_provider/_polygon_discovery.py +97 -0
- webviz_subsurface/_providers/ensemble_polygon_provider/_provider_impl_file.py +226 -0
- webviz_subsurface/_providers/ensemble_polygon_provider/ensemble_polygon_provider.py +53 -0
- webviz_subsurface/_providers/ensemble_polygon_provider/ensemble_polygon_provider_factory.py +99 -0
- webviz_subsurface/_providers/ensemble_polygon_provider/polygon_server.py +125 -0
- webviz_subsurface/plugins/_co2_leakage/_plugin.py +531 -377
- webviz_subsurface/plugins/_co2_leakage/_utilities/_misc.py +9 -0
- webviz_subsurface/plugins/_co2_leakage/_utilities/callbacks.py +169 -173
- webviz_subsurface/plugins/_co2_leakage/_utilities/co2volume.py +329 -84
- webviz_subsurface/plugins/_co2_leakage/_utilities/containment_data_provider.py +147 -0
- webviz_subsurface/plugins/_co2_leakage/_utilities/ensemble_well_picks.py +105 -0
- webviz_subsurface/plugins/_co2_leakage/_utilities/generic.py +170 -2
- webviz_subsurface/plugins/_co2_leakage/_utilities/initialization.py +189 -96
- webviz_subsurface/plugins/_co2_leakage/_utilities/polygon_handler.py +60 -0
- webviz_subsurface/plugins/_co2_leakage/_utilities/summary_graphs.py +77 -173
- webviz_subsurface/plugins/_co2_leakage/_utilities/surface_publishing.py +29 -21
- webviz_subsurface/plugins/_co2_leakage/_utilities/unsmry_data_provider.py +108 -0
- webviz_subsurface/plugins/_co2_leakage/views/mainview/mainview.py +30 -18
- webviz_subsurface/plugins/_co2_leakage/views/mainview/settings.py +805 -343
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/METADATA +2 -2
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/RECORD +30 -19
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/WHEEL +1 -1
- /webviz_subsurface/plugins/_co2_leakage/_utilities/{fault_polygons.py → fault_polygons_handler.py} +0 -0
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/LICENSE +0 -0
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/LICENSE.chromedriver +0 -0
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/entry_points.txt +0 -0
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/top_level.txt +0 -0
|
@@ -8,6 +8,7 @@ from webviz_config import WebvizPluginABC, WebvizSettings
|
|
|
8
8
|
from webviz_config.utils import StrEnum, callback_typecheck
|
|
9
9
|
|
|
10
10
|
from webviz_subsurface._providers import FaultPolygonsServer, SurfaceImageServer
|
|
11
|
+
from webviz_subsurface._providers.ensemble_polygon_provider import PolygonServer
|
|
11
12
|
from webviz_subsurface.plugins._co2_leakage._utilities.callbacks import (
|
|
12
13
|
SurfaceData,
|
|
13
14
|
create_map_annotations,
|
|
@@ -17,6 +18,7 @@ from webviz_subsurface.plugins._co2_leakage._utilities.callbacks import (
|
|
|
17
18
|
generate_containment_figures,
|
|
18
19
|
generate_unsmry_figures,
|
|
19
20
|
get_plume_polygon,
|
|
21
|
+
make_plot_ids,
|
|
20
22
|
process_containment_info,
|
|
21
23
|
process_summed_mass,
|
|
22
24
|
process_visualization_info,
|
|
@@ -24,22 +26,28 @@ from webviz_subsurface.plugins._co2_leakage._utilities.callbacks import (
|
|
|
24
26
|
readable_name,
|
|
25
27
|
set_plot_ids,
|
|
26
28
|
)
|
|
27
|
-
from webviz_subsurface.plugins._co2_leakage._utilities.
|
|
29
|
+
from webviz_subsurface.plugins._co2_leakage._utilities.fault_polygons_handler import (
|
|
28
30
|
FaultPolygonsHandler,
|
|
29
31
|
)
|
|
30
32
|
from webviz_subsurface.plugins._co2_leakage._utilities.generic import (
|
|
33
|
+
BoundarySettings,
|
|
31
34
|
Co2MassScale,
|
|
32
35
|
Co2VolumeScale,
|
|
33
36
|
GraphSource,
|
|
34
37
|
MapAttribute,
|
|
38
|
+
MapThresholds,
|
|
39
|
+
MapType,
|
|
35
40
|
)
|
|
36
41
|
from webviz_subsurface.plugins._co2_leakage._utilities.initialization import (
|
|
42
|
+
init_containment_data_providers,
|
|
43
|
+
init_dictionary_of_content,
|
|
37
44
|
init_map_attribute_names,
|
|
38
45
|
init_menu_options,
|
|
46
|
+
init_polygon_provider_handlers,
|
|
47
|
+
init_realizations,
|
|
39
48
|
init_surface_providers,
|
|
40
|
-
|
|
49
|
+
init_unsmry_data_providers,
|
|
41
50
|
init_well_pick_provider,
|
|
42
|
-
process_files,
|
|
43
51
|
)
|
|
44
52
|
from webviz_subsurface.plugins._co2_leakage.views.mainview.mainview import (
|
|
45
53
|
MainView,
|
|
@@ -61,8 +69,6 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
61
69
|
ensemble
|
|
62
70
|
|
|
63
71
|
* **`ensembles`:** Which ensembles in `shared_settings` to visualize.
|
|
64
|
-
* **`file_containment_boundary`:** Path to a polygon representing the containment area
|
|
65
|
-
* **`file_hazardous_boundary`:** Path to a polygon representing the hazardous area
|
|
66
72
|
* **`well_pick_file`:** Path to a file containing well picks
|
|
67
73
|
* **`plume_mass_relpath`:** Path to a table of co2 containment data (amount of
|
|
68
74
|
CO2 outside/inside a boundary), for co2 mass. Relative to each realization.
|
|
@@ -81,6 +87,8 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
81
87
|
names and surface names used in the well pick file
|
|
82
88
|
* **`map_surface_names_to_fault_polygons`:** Optional mapping between surface map
|
|
83
89
|
names and surface names used by the fault polygons
|
|
90
|
+
* **`boundary_settings`:** Settings (paths etc) for polygons representing the
|
|
91
|
+
containment and hazardous areas
|
|
84
92
|
"""
|
|
85
93
|
|
|
86
94
|
class Ids(StrEnum):
|
|
@@ -94,8 +102,6 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
94
102
|
app: Dash,
|
|
95
103
|
webviz_settings: WebvizSettings,
|
|
96
104
|
ensembles: List[str],
|
|
97
|
-
file_containment_boundary: Optional[str] = None,
|
|
98
|
-
file_hazardous_boundary: Optional[str] = None,
|
|
99
105
|
well_pick_file: Optional[str] = None,
|
|
100
106
|
plume_mass_relpath: str = TABLES_PATH + "/plume_mass.csv",
|
|
101
107
|
plume_actual_volume_relpath: str = TABLES_PATH + "/plume_actual_volume.csv",
|
|
@@ -105,6 +111,7 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
105
111
|
map_attribute_names: Optional[Dict[str, str]] = None,
|
|
106
112
|
map_surface_names_to_well_pick_names: Optional[Dict[str, str]] = None,
|
|
107
113
|
map_surface_names_to_fault_polygons: Optional[Dict[str, str]] = None,
|
|
114
|
+
boundary_settings: Optional[BoundarySettings] = None,
|
|
108
115
|
):
|
|
109
116
|
super().__init__()
|
|
110
117
|
self._error_message = ""
|
|
@@ -115,21 +122,14 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
115
122
|
]
|
|
116
123
|
for ensemble_name in ensembles
|
|
117
124
|
}
|
|
118
|
-
(
|
|
119
|
-
containment_poly_dict,
|
|
120
|
-
hazardous_poly_dict,
|
|
121
|
-
well_pick_dict,
|
|
122
|
-
) = process_files(
|
|
123
|
-
file_containment_boundary,
|
|
124
|
-
file_hazardous_boundary,
|
|
125
|
-
well_pick_file,
|
|
126
|
-
ensemble_paths,
|
|
127
|
-
)
|
|
128
|
-
self._polygon_files = [containment_poly_dict, hazardous_poly_dict]
|
|
125
|
+
self._realizations_per_ensemble = init_realizations(ensemble_paths)
|
|
129
126
|
self._surface_server = SurfaceImageServer.instance(app)
|
|
130
127
|
self._polygons_server = FaultPolygonsServer.instance(app)
|
|
131
|
-
|
|
132
|
-
|
|
128
|
+
self._map_attribute_names = init_map_attribute_names(
|
|
129
|
+
webviz_settings, ensembles, map_attribute_names
|
|
130
|
+
)
|
|
131
|
+
self._map_thresholds = MapThresholds(self._map_attribute_names)
|
|
132
|
+
self._threshold_ids = list(self._map_thresholds.standard_thresholds.keys())
|
|
133
133
|
# Surfaces
|
|
134
134
|
self._ensemble_surface_providers = init_surface_providers(
|
|
135
135
|
webviz_settings, ensembles
|
|
@@ -145,25 +145,27 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
145
145
|
for ens in ensembles
|
|
146
146
|
}
|
|
147
147
|
# CO2 containment
|
|
148
|
-
self._co2_table_providers =
|
|
148
|
+
self._co2_table_providers = init_containment_data_providers(
|
|
149
149
|
ensemble_paths,
|
|
150
150
|
plume_mass_relpath,
|
|
151
151
|
)
|
|
152
|
-
self._co2_actual_volume_table_providers =
|
|
152
|
+
self._co2_actual_volume_table_providers = init_containment_data_providers(
|
|
153
153
|
ensemble_paths,
|
|
154
154
|
plume_actual_volume_relpath,
|
|
155
155
|
)
|
|
156
|
-
self._unsmry_providers = (
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
156
|
+
self._unsmry_providers = init_unsmry_data_providers(
|
|
157
|
+
ensemble_paths,
|
|
158
|
+
unsmry_relpath,
|
|
159
|
+
)
|
|
160
|
+
self._polygon_handlers = init_polygon_provider_handlers(
|
|
161
|
+
PolygonServer.instance(app),
|
|
162
|
+
ensemble_paths,
|
|
163
|
+
boundary_settings,
|
|
163
164
|
)
|
|
164
165
|
# Well picks
|
|
165
166
|
self._well_pick_provider = init_well_pick_provider(
|
|
166
|
-
|
|
167
|
+
ensemble_paths,
|
|
168
|
+
well_pick_file,
|
|
167
169
|
map_surface_names_to_well_pick_names,
|
|
168
170
|
)
|
|
169
171
|
# Phase (in case of residual trapping), zone and region options
|
|
@@ -171,8 +173,11 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
171
173
|
ensemble_paths,
|
|
172
174
|
self._co2_table_providers,
|
|
173
175
|
self._co2_actual_volume_table_providers,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
+
self._unsmry_providers,
|
|
177
|
+
)
|
|
178
|
+
self._content = init_dictionary_of_content(
|
|
179
|
+
self._menu_options,
|
|
180
|
+
len(self._map_attribute_names.mapping) > 0,
|
|
176
181
|
)
|
|
177
182
|
except Exception as err:
|
|
178
183
|
self._error_message = f"Plugin initialization failed: {err}"
|
|
@@ -180,29 +185,37 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
180
185
|
|
|
181
186
|
self._summed_co2: Dict[str, Any] = {}
|
|
182
187
|
self._visualization_info = {
|
|
183
|
-
"
|
|
188
|
+
"thresholds": self._map_thresholds.standard_thresholds,
|
|
184
189
|
"n_clicks": 0,
|
|
185
190
|
"change": False,
|
|
186
|
-
"unit": "
|
|
191
|
+
"unit": "tons",
|
|
187
192
|
}
|
|
193
|
+
self._plot_id = ""
|
|
188
194
|
self._color_tables = co2leakage_color_tables()
|
|
189
|
-
self._well_pick_names = {
|
|
190
|
-
ens:
|
|
191
|
-
|
|
195
|
+
self._well_pick_names: Dict[str, List[str]] = {
|
|
196
|
+
ens: (
|
|
197
|
+
self._well_pick_provider[ens].well_names
|
|
198
|
+
if ens in self._well_pick_provider
|
|
199
|
+
else []
|
|
200
|
+
)
|
|
201
|
+
for ens in ensembles
|
|
192
202
|
}
|
|
193
203
|
self.add_shared_settings_group(
|
|
194
204
|
ViewSettings(
|
|
195
205
|
ensemble_paths,
|
|
206
|
+
self._realizations_per_ensemble,
|
|
196
207
|
self._ensemble_surface_providers,
|
|
197
208
|
initial_surface,
|
|
198
209
|
self._map_attribute_names,
|
|
210
|
+
self._map_thresholds,
|
|
199
211
|
[c["name"] for c in self._color_tables], # type: ignore
|
|
200
212
|
self._well_pick_names,
|
|
201
213
|
self._menu_options,
|
|
214
|
+
self._content,
|
|
202
215
|
),
|
|
203
216
|
self.Ids.MAIN_SETTINGS,
|
|
204
217
|
)
|
|
205
|
-
self.add_view(MainView(self._color_tables), self.Ids.MAIN_VIEW)
|
|
218
|
+
self.add_view(MainView(self._color_tables, self._content), self.Ids.MAIN_VIEW)
|
|
206
219
|
|
|
207
220
|
@property
|
|
208
221
|
def layout(self) -> html.Div:
|
|
@@ -225,8 +238,24 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
225
238
|
|
|
226
239
|
def _ensemble_dates(self, ens: str) -> List[str]:
|
|
227
240
|
surface_provider = self._ensemble_surface_providers[ens]
|
|
228
|
-
|
|
229
|
-
|
|
241
|
+
date_map_attribute = next(
|
|
242
|
+
(
|
|
243
|
+
k
|
|
244
|
+
for k in self._map_attribute_names.filtered_values
|
|
245
|
+
if MapType[k.name].value != "MIGRATION_TIME"
|
|
246
|
+
),
|
|
247
|
+
None,
|
|
248
|
+
)
|
|
249
|
+
att_name = (
|
|
250
|
+
self._map_attribute_names[date_map_attribute]
|
|
251
|
+
if date_map_attribute is not None
|
|
252
|
+
else None
|
|
253
|
+
)
|
|
254
|
+
dates = (
|
|
255
|
+
None
|
|
256
|
+
if att_name is None
|
|
257
|
+
else surface_provider.surface_dates_for_attribute(att_name)
|
|
258
|
+
)
|
|
230
259
|
if dates is None:
|
|
231
260
|
raise ValueError(f"Failed to fetch dates for attribute '{att_name}'")
|
|
232
261
|
return dates
|
|
@@ -236,329 +265,450 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
236
265
|
def _set_callbacks(self) -> None:
|
|
237
266
|
# Cannot avoid many arguments since all the parameters are needed
|
|
238
267
|
# to determine what to plot
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
y_max_auto: List[str],
|
|
271
|
-
y_max_val: Optional[float],
|
|
272
|
-
zone: Optional[str],
|
|
273
|
-
region: Optional[str],
|
|
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
|
|
282
|
-
cont_info = process_containment_info(
|
|
283
|
-
zone,
|
|
284
|
-
region,
|
|
285
|
-
phase,
|
|
286
|
-
containment,
|
|
287
|
-
color_choice,
|
|
288
|
-
mark_choice,
|
|
289
|
-
sorting,
|
|
290
|
-
self._menu_options[ensemble][source],
|
|
268
|
+
if self._content["any_table"]:
|
|
269
|
+
# pylint: disable=too-many-arguments
|
|
270
|
+
@callback(
|
|
271
|
+
Output(self._view_component(MapViewElement.Ids.BAR_PLOT), "figure"),
|
|
272
|
+
Output(self._view_component(MapViewElement.Ids.TIME_PLOT), "figure"),
|
|
273
|
+
Output(
|
|
274
|
+
self._view_component(MapViewElement.Ids.STATISTICS_PLOT),
|
|
275
|
+
"figure",
|
|
276
|
+
),
|
|
277
|
+
Input(self._settings_component(ViewSettings.Ids.ENSEMBLE), "value"),
|
|
278
|
+
Input(self._settings_component(ViewSettings.Ids.GRAPH_SOURCE), "value"),
|
|
279
|
+
Input(self._settings_component(ViewSettings.Ids.CO2_SCALE), "value"),
|
|
280
|
+
Input(self._settings_component(ViewSettings.Ids.REALIZATION), "value"),
|
|
281
|
+
Input(
|
|
282
|
+
self._settings_component(ViewSettings.Ids.Y_MIN_AUTO_GRAPH), "value"
|
|
283
|
+
),
|
|
284
|
+
Input(self._settings_component(ViewSettings.Ids.Y_MIN_GRAPH), "value"),
|
|
285
|
+
Input(
|
|
286
|
+
self._settings_component(ViewSettings.Ids.Y_MAX_AUTO_GRAPH), "value"
|
|
287
|
+
),
|
|
288
|
+
Input(self._settings_component(ViewSettings.Ids.Y_MAX_GRAPH), "value"),
|
|
289
|
+
Input(self._settings_component(ViewSettings.Ids.ZONE), "value"),
|
|
290
|
+
Input(self._settings_component(ViewSettings.Ids.REGION), "value"),
|
|
291
|
+
Input(self._settings_component(ViewSettings.Ids.PHASE), "value"),
|
|
292
|
+
Input(self._settings_component(ViewSettings.Ids.CONTAINMENT), "value"),
|
|
293
|
+
Input(self._settings_component(ViewSettings.Ids.PLUME_GROUP), "value"),
|
|
294
|
+
Input(self._settings_component(ViewSettings.Ids.COLOR_BY), "value"),
|
|
295
|
+
Input(self._settings_component(ViewSettings.Ids.MARK_BY), "value"),
|
|
296
|
+
Input(self._settings_component(ViewSettings.Ids.SORT_PLOT), "value"),
|
|
297
|
+
Input(self._settings_component(ViewSettings.Ids.REAL_OR_STAT), "value"),
|
|
298
|
+
Input(self._settings_component(ViewSettings.Ids.DATE_OPTION), "value"),
|
|
291
299
|
)
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
]
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
300
|
+
@callback_typecheck
|
|
301
|
+
def update_graphs(
|
|
302
|
+
ensemble: str,
|
|
303
|
+
source: GraphSource,
|
|
304
|
+
co2_scale: Union[Co2MassScale, Co2VolumeScale],
|
|
305
|
+
realizations: List[int],
|
|
306
|
+
y_min_auto: List[str],
|
|
307
|
+
y_min_val: Optional[float],
|
|
308
|
+
y_max_auto: List[str],
|
|
309
|
+
y_max_val: Optional[float],
|
|
310
|
+
zone: Optional[str],
|
|
311
|
+
region: Optional[str],
|
|
312
|
+
phase: str,
|
|
313
|
+
containment: str,
|
|
314
|
+
plume_group: str,
|
|
315
|
+
color_choice: str,
|
|
316
|
+
mark_choice: Optional[str],
|
|
317
|
+
sorting: str,
|
|
318
|
+
lines_to_show: str,
|
|
319
|
+
date_option: str,
|
|
320
|
+
) -> Tuple[Dict, go.Figure, go.Figure, go.Figure]:
|
|
321
|
+
# pylint: disable=too-many-locals
|
|
322
|
+
figs = [no_update] * 3
|
|
323
|
+
cont_info = process_containment_info(
|
|
324
|
+
zone,
|
|
325
|
+
region,
|
|
326
|
+
phase,
|
|
327
|
+
containment,
|
|
328
|
+
plume_group,
|
|
329
|
+
color_choice,
|
|
330
|
+
mark_choice,
|
|
331
|
+
sorting,
|
|
332
|
+
lines_to_show,
|
|
333
|
+
date_option,
|
|
334
|
+
self._menu_options[ensemble][source],
|
|
335
|
+
)
|
|
336
|
+
if source in [
|
|
337
|
+
GraphSource.CONTAINMENT_MASS,
|
|
338
|
+
GraphSource.CONTAINMENT_ACTUAL_VOLUME,
|
|
339
|
+
]:
|
|
340
|
+
plot_ids = make_plot_ids(
|
|
341
|
+
ensemble,
|
|
342
|
+
source,
|
|
317
343
|
co2_scale,
|
|
318
|
-
realizations[0],
|
|
319
|
-
y_limits,
|
|
320
344
|
cont_info,
|
|
345
|
+
realizations,
|
|
346
|
+
lines_to_show,
|
|
347
|
+
len(figs),
|
|
321
348
|
)
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
349
|
+
cont_info["update_first_figure"] = self._plot_id != plot_ids[0]
|
|
350
|
+
self._plot_id = plot_ids[0]
|
|
351
|
+
y_limits = [
|
|
352
|
+
y_min_val if len(y_min_auto) == 0 else None,
|
|
353
|
+
y_max_val if len(y_max_auto) == 0 else None,
|
|
354
|
+
]
|
|
355
|
+
if (
|
|
356
|
+
source == GraphSource.CONTAINMENT_MASS
|
|
357
|
+
and ensemble in self._co2_table_providers
|
|
358
|
+
):
|
|
359
|
+
figs[: len(figs)] = generate_containment_figures(
|
|
329
360
|
self._co2_table_providers[ensemble],
|
|
361
|
+
co2_scale,
|
|
362
|
+
realizations,
|
|
363
|
+
y_limits,
|
|
364
|
+
cont_info,
|
|
330
365
|
)
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
366
|
+
elif (
|
|
367
|
+
source == GraphSource.CONTAINMENT_ACTUAL_VOLUME
|
|
368
|
+
and ensemble in self._co2_actual_volume_table_providers
|
|
369
|
+
):
|
|
370
|
+
figs[: len(figs)] = generate_containment_figures(
|
|
371
|
+
self._co2_actual_volume_table_providers[ensemble],
|
|
372
|
+
co2_scale,
|
|
373
|
+
realizations,
|
|
374
|
+
y_limits,
|
|
375
|
+
cont_info,
|
|
376
|
+
)
|
|
377
|
+
set_plot_ids(figs, plot_ids)
|
|
378
|
+
elif source == GraphSource.UNSMRY:
|
|
379
|
+
if self._unsmry_providers is not None:
|
|
380
|
+
if ensemble in self._unsmry_providers:
|
|
381
|
+
figs[0] = go.Figure()
|
|
382
|
+
figs[1] = generate_unsmry_figures(
|
|
383
|
+
self._unsmry_providers[ensemble],
|
|
384
|
+
co2_scale,
|
|
385
|
+
self._co2_table_providers[ensemble],
|
|
386
|
+
)
|
|
387
|
+
figs[2] = go.Figure()
|
|
388
|
+
else:
|
|
389
|
+
LOGGER.warning(
|
|
390
|
+
"""UNSMRY file has not been specified as input.
|
|
391
|
+
Please use unsmry_relpath in the configuration."""
|
|
392
|
+
)
|
|
393
|
+
return figs # type: ignore
|
|
357
394
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
395
|
+
@callback(
|
|
396
|
+
Output(self._settings_component(ViewSettings.Ids.CO2_SCALE), "options"),
|
|
397
|
+
Output(self._settings_component(ViewSettings.Ids.CO2_SCALE), "value"),
|
|
398
|
+
Input(self._settings_component(ViewSettings.Ids.GRAPH_SOURCE), "value"),
|
|
399
|
+
)
|
|
400
|
+
def make_unit_list(
|
|
401
|
+
attribute: str,
|
|
402
|
+
) -> Union[
|
|
403
|
+
Tuple[List[Any], Co2MassScale],
|
|
404
|
+
Tuple[List[Any], Co2VolumeScale],
|
|
366
405
|
]:
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
@callback(
|
|
371
|
-
Output(self._settings_component(ViewSettings.Ids.CO2_SCALE), "options"),
|
|
372
|
-
Output(self._settings_component(ViewSettings.Ids.CO2_SCALE), "value"),
|
|
373
|
-
Input(self._settings_component(ViewSettings.Ids.GRAPH_SOURCE), "value"),
|
|
374
|
-
)
|
|
375
|
-
def make_unit_list(
|
|
376
|
-
attribute: str,
|
|
377
|
-
) -> Union[Tuple[List[Any], Co2MassScale], Tuple[List[Any], Co2VolumeScale],]:
|
|
378
|
-
if attribute == GraphSource.CONTAINMENT_ACTUAL_VOLUME:
|
|
379
|
-
return list(Co2VolumeScale), Co2VolumeScale.BILLION_CUBIC_METERS
|
|
380
|
-
return list(Co2MassScale), Co2MassScale.MTONS
|
|
406
|
+
if attribute == GraphSource.CONTAINMENT_ACTUAL_VOLUME:
|
|
407
|
+
return list(Co2VolumeScale), Co2VolumeScale.BILLION_CUBIC_METERS
|
|
408
|
+
return list(Co2MassScale), Co2MassScale.MTONS
|
|
381
409
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
ensemble: str,
|
|
391
|
-
) -> Tuple[List[Any], List[str], Dict[Any, Any], Dict[Any, Any]]:
|
|
392
|
-
return (
|
|
393
|
-
[{"label": i, "value": i} for i in self._well_pick_names[ensemble]],
|
|
394
|
-
self._well_pick_names[ensemble],
|
|
395
|
-
{
|
|
396
|
-
"display": "block" if self._well_pick_names[ensemble] else "none",
|
|
397
|
-
"height": f"{len(self._well_pick_names[ensemble]) * 22}px",
|
|
398
|
-
},
|
|
399
|
-
{
|
|
400
|
-
"flex": 3,
|
|
401
|
-
"minWidth": "20px",
|
|
402
|
-
"display": "block" if self._well_pick_names[ensemble] else "none",
|
|
403
|
-
},
|
|
410
|
+
@callback(
|
|
411
|
+
Output(
|
|
412
|
+
self._settings_component(ViewSettings.Ids.REAL_OR_STAT), "style"
|
|
413
|
+
),
|
|
414
|
+
Output(
|
|
415
|
+
self._settings_component(ViewSettings.Ids.Y_LIM_OPTIONS), "style"
|
|
416
|
+
),
|
|
417
|
+
Input(self._settings_component(ViewSettings.Ids.REALIZATION), "value"),
|
|
404
418
|
)
|
|
419
|
+
def toggle_time_plot_options_visibility(
|
|
420
|
+
realizations: List[int],
|
|
421
|
+
) -> Tuple[Dict[str, str], Dict[str, str]]:
|
|
422
|
+
if len(realizations) == 1:
|
|
423
|
+
return (
|
|
424
|
+
{"display": "none"},
|
|
425
|
+
{"display": "flex", "flex-direction": "column"},
|
|
426
|
+
)
|
|
427
|
+
return (
|
|
428
|
+
{"display": "flex", "flex-direction": "row"},
|
|
429
|
+
{"display": "none"},
|
|
430
|
+
)
|
|
405
431
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
Output(self._view_component(MapViewElement.Ids.DECKGL_MAP), "views"),
|
|
413
|
-
Input(self._settings_component(ViewSettings.Ids.PROPERTY), "value"),
|
|
414
|
-
Input(self._view_component(MapViewElement.Ids.DATE_SLIDER), "value"),
|
|
415
|
-
Input(self._settings_component(ViewSettings.Ids.FORMATION), "value"),
|
|
416
|
-
Input(self._settings_component(ViewSettings.Ids.REALIZATION), "value"),
|
|
417
|
-
Input(self._settings_component(ViewSettings.Ids.STATISTIC), "value"),
|
|
418
|
-
Input(self._settings_component(ViewSettings.Ids.COLOR_SCALE), "value"),
|
|
419
|
-
Input(self._settings_component(ViewSettings.Ids.CM_MIN_AUTO), "value"),
|
|
420
|
-
Input(self._settings_component(ViewSettings.Ids.CM_MIN), "value"),
|
|
421
|
-
Input(self._settings_component(ViewSettings.Ids.CM_MAX_AUTO), "value"),
|
|
422
|
-
Input(self._settings_component(ViewSettings.Ids.CM_MAX), "value"),
|
|
423
|
-
Input(self._settings_component(ViewSettings.Ids.PLUME_THRESHOLD), "value"),
|
|
424
|
-
Input(self._settings_component(ViewSettings.Ids.PLUME_SMOOTHING), "value"),
|
|
425
|
-
Input(
|
|
426
|
-
self._settings_component(ViewSettings.Ids.VISUALIZATION_THRESHOLD),
|
|
427
|
-
"value",
|
|
428
|
-
),
|
|
429
|
-
Input(
|
|
430
|
-
self._settings_component(ViewSettings.Ids.VISUALIZATION_UPDATE),
|
|
431
|
-
"n_clicks",
|
|
432
|
-
),
|
|
433
|
-
Input(self._settings_component(ViewSettings.Ids.MASS_UNIT), "value"),
|
|
434
|
-
Input(ViewSettings.Ids.OPTIONS_DIALOG_OPTIONS, "value"),
|
|
435
|
-
Input(ViewSettings.Ids.OPTIONS_DIALOG_WELL_FILTER, "value"),
|
|
436
|
-
Input(self._settings_component(ViewSettings.Ids.ENSEMBLE), "value"),
|
|
437
|
-
State(self._view_component(MapViewElement.Ids.DECKGL_MAP), "views"),
|
|
438
|
-
)
|
|
439
|
-
def update_map_attribute(
|
|
440
|
-
attribute: MapAttribute,
|
|
441
|
-
date: int,
|
|
442
|
-
formation: str,
|
|
443
|
-
realization: List[int],
|
|
444
|
-
statistic: str,
|
|
445
|
-
color_map_name: str,
|
|
446
|
-
cm_min_auto: List[str],
|
|
447
|
-
cm_min_val: Optional[float],
|
|
448
|
-
cm_max_auto: List[str],
|
|
449
|
-
cm_max_val: Optional[float],
|
|
450
|
-
plume_threshold: Optional[float],
|
|
451
|
-
plume_smoothing: Optional[float],
|
|
452
|
-
visualization_threshold: Optional[float],
|
|
453
|
-
visualization_update: int,
|
|
454
|
-
mass_unit: str,
|
|
455
|
-
options_dialog_options: List[int],
|
|
456
|
-
selected_wells: List[str],
|
|
457
|
-
ensemble: str,
|
|
458
|
-
current_views: List[Any],
|
|
459
|
-
) -> Tuple[List[Dict[Any, Any]], List[Any], Dict[Any, Any]]:
|
|
460
|
-
# Unable to clear cache (when needed) without the protected member
|
|
461
|
-
# pylint: disable=protected-access
|
|
462
|
-
self._visualization_info = process_visualization_info(
|
|
463
|
-
visualization_update,
|
|
464
|
-
visualization_threshold,
|
|
465
|
-
mass_unit,
|
|
466
|
-
self._visualization_info,
|
|
467
|
-
self._surface_server._image_cache,
|
|
432
|
+
if self._content["maps"]:
|
|
433
|
+
|
|
434
|
+
@callback(
|
|
435
|
+
Output(self._view_component(MapViewElement.Ids.DATE_SLIDER), "marks"),
|
|
436
|
+
Output(self._view_component(MapViewElement.Ids.DATE_SLIDER), "value"),
|
|
437
|
+
Input(self._settings_component(ViewSettings.Ids.ENSEMBLE), "value"),
|
|
468
438
|
)
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
439
|
+
def set_dates(
|
|
440
|
+
ensemble: str,
|
|
441
|
+
) -> Tuple[Dict[int, Dict[str, Any]], Optional[int]]:
|
|
442
|
+
if ensemble is None:
|
|
443
|
+
return {}, None
|
|
444
|
+
# Dates
|
|
445
|
+
date_list = self._ensemble_dates(ensemble)
|
|
446
|
+
dates = {
|
|
447
|
+
i: {
|
|
448
|
+
"label": f"{d[:4]}",
|
|
449
|
+
"style": {"writingMode": "vertical-rl"},
|
|
450
|
+
}
|
|
451
|
+
for i, d in enumerate(date_list)
|
|
482
452
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
453
|
+
if len(dates.keys()) > 0:
|
|
454
|
+
return dates, max(dates.keys())
|
|
455
|
+
return dates, None
|
|
456
|
+
|
|
457
|
+
@callback(
|
|
458
|
+
Output(self._view_component(MapViewElement.Ids.DATE_WRAPPER), "style"),
|
|
459
|
+
Input(self._settings_component(ViewSettings.Ids.PROPERTY), "value"),
|
|
460
|
+
)
|
|
461
|
+
def toggle_date_slider(attribute: str) -> Dict[str, str]:
|
|
462
|
+
if MapType[MapAttribute(attribute).name].value == "MIGRATION_TIME":
|
|
463
|
+
return {"display": "none"}
|
|
464
|
+
return {}
|
|
465
|
+
|
|
466
|
+
@callback(
|
|
467
|
+
Output(ViewSettings.Ids.OPTIONS_DIALOG_WELL_FILTER, "options"),
|
|
468
|
+
Output(ViewSettings.Ids.OPTIONS_DIALOG_WELL_FILTER, "value"),
|
|
469
|
+
Output(ViewSettings.Ids.OPTIONS_DIALOG_WELL_FILTER, "style"),
|
|
470
|
+
Output(ViewSettings.Ids.WELL_FILTER_HEADER, "style"),
|
|
471
|
+
Input(self._settings_component(ViewSettings.Ids.ENSEMBLE), "value"),
|
|
472
|
+
)
|
|
473
|
+
def set_well_options(
|
|
474
|
+
ensemble: str,
|
|
475
|
+
) -> Tuple[List[Any], List[str], Dict[Any, Any], Dict[Any, Any]]:
|
|
476
|
+
return (
|
|
477
|
+
[{"label": i, "value": i} for i in self._well_pick_names[ensemble]],
|
|
478
|
+
self._well_pick_names[ensemble],
|
|
479
|
+
{
|
|
480
|
+
"display": (
|
|
481
|
+
"block" if self._well_pick_names[ensemble] else "none"
|
|
482
|
+
),
|
|
483
|
+
"height": f"{len(self._well_pick_names[ensemble]) * 22}px",
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
"flex": 3,
|
|
487
|
+
"minWidth": "20px",
|
|
488
|
+
"display": (
|
|
489
|
+
"block" if self._well_pick_names[ensemble] else "none"
|
|
490
|
+
),
|
|
491
|
+
},
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
# Cannot avoid many arguments and/or locals since all layers of the DeckGL map
|
|
495
|
+
# need to be updated simultaneously
|
|
496
|
+
# pylint: disable=too-many-arguments,too-many-locals
|
|
497
|
+
@callback(
|
|
498
|
+
Output(self._view_component(MapViewElement.Ids.DECKGL_MAP), "layers"),
|
|
499
|
+
Output(self._view_component(MapViewElement.Ids.DECKGL_MAP), "children"),
|
|
500
|
+
Output(self._view_component(MapViewElement.Ids.DECKGL_MAP), "views"),
|
|
501
|
+
inputs={
|
|
502
|
+
"attribute": Input(
|
|
503
|
+
self._settings_component(ViewSettings.Ids.PROPERTY), "value"
|
|
497
504
|
),
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
cm_max_val if len(cm_max_auto) == 0 else None,
|
|
505
|
+
"date": Input(
|
|
506
|
+
self._view_component(MapViewElement.Ids.DATE_SLIDER), "value"
|
|
501
507
|
),
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
508
|
+
"formation": Input(
|
|
509
|
+
self._settings_component(ViewSettings.Ids.FORMATION), "value"
|
|
510
|
+
),
|
|
511
|
+
"realization": Input(
|
|
512
|
+
self._settings_component(ViewSettings.Ids.REALIZATION), "value"
|
|
513
|
+
),
|
|
514
|
+
"statistic": Input(
|
|
515
|
+
self._settings_component(ViewSettings.Ids.STATISTIC), "value"
|
|
516
|
+
),
|
|
517
|
+
"color_map_name": Input(
|
|
518
|
+
self._settings_component(ViewSettings.Ids.COLOR_SCALE), "value"
|
|
519
|
+
),
|
|
520
|
+
"cm_min_auto": Input(
|
|
521
|
+
self._settings_component(ViewSettings.Ids.CM_MIN_AUTO), "value"
|
|
522
|
+
),
|
|
523
|
+
"cm_min_val": Input(
|
|
524
|
+
self._settings_component(ViewSettings.Ids.CM_MIN), "value"
|
|
525
|
+
),
|
|
526
|
+
"cm_max_auto": Input(
|
|
527
|
+
self._settings_component(ViewSettings.Ids.CM_MAX_AUTO), "value"
|
|
528
|
+
),
|
|
529
|
+
"cm_max_val": Input(
|
|
530
|
+
self._settings_component(ViewSettings.Ids.CM_MAX), "value"
|
|
531
|
+
),
|
|
532
|
+
"plume_threshold": Input(
|
|
533
|
+
self._settings_component(ViewSettings.Ids.PLUME_THRESHOLD),
|
|
534
|
+
"value",
|
|
535
|
+
),
|
|
536
|
+
"plume_smoothing": Input(
|
|
537
|
+
self._settings_component(ViewSettings.Ids.PLUME_SMOOTHING),
|
|
538
|
+
"value",
|
|
539
|
+
),
|
|
540
|
+
"visualization_update": Input(
|
|
541
|
+
self._settings_component(ViewSettings.Ids.VISUALIZATION_UPDATE),
|
|
542
|
+
"n_clicks",
|
|
543
|
+
),
|
|
544
|
+
"mass_unit": Input(
|
|
545
|
+
self._settings_component(ViewSettings.Ids.MASS_UNIT), "value"
|
|
546
|
+
),
|
|
547
|
+
"mass_unit_update": Input(
|
|
548
|
+
self._settings_component(ViewSettings.Ids.MASS_UNIT_UPDATE),
|
|
549
|
+
"n_clicks",
|
|
550
|
+
),
|
|
551
|
+
"options_dialog_options": Input(
|
|
552
|
+
ViewSettings.Ids.OPTIONS_DIALOG_OPTIONS, "value"
|
|
553
|
+
),
|
|
554
|
+
"selected_wells": Input(
|
|
555
|
+
ViewSettings.Ids.OPTIONS_DIALOG_WELL_FILTER, "value"
|
|
556
|
+
),
|
|
557
|
+
"ensemble": Input(
|
|
558
|
+
self._settings_component(ViewSettings.Ids.ENSEMBLE), "value"
|
|
559
|
+
),
|
|
560
|
+
"current_views": State(
|
|
561
|
+
self._view_component(MapViewElement.Ids.DECKGL_MAP), "views"
|
|
562
|
+
),
|
|
563
|
+
"thresholds": [Input(id, "value") for id in self._threshold_ids],
|
|
564
|
+
},
|
|
517
565
|
)
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
566
|
+
def update_map_attribute(
|
|
567
|
+
attribute: MapAttribute,
|
|
568
|
+
date: int,
|
|
569
|
+
formation: str,
|
|
570
|
+
realization: List[int],
|
|
571
|
+
statistic: str,
|
|
572
|
+
color_map_name: str,
|
|
573
|
+
cm_min_auto: List[str],
|
|
574
|
+
cm_min_val: Optional[float],
|
|
575
|
+
cm_max_auto: List[str],
|
|
576
|
+
cm_max_val: Optional[float],
|
|
577
|
+
plume_threshold: Optional[float],
|
|
578
|
+
plume_smoothing: Optional[float],
|
|
579
|
+
visualization_update: int,
|
|
580
|
+
mass_unit: str,
|
|
581
|
+
mass_unit_update: int,
|
|
582
|
+
options_dialog_options: List[int],
|
|
583
|
+
selected_wells: List[str],
|
|
584
|
+
ensemble: str,
|
|
585
|
+
current_views: List[Any],
|
|
586
|
+
thresholds: List[float],
|
|
587
|
+
) -> Tuple[List[Dict[Any, Any]], Optional[List[Any]], Dict[Any, Any]]:
|
|
588
|
+
# Unable to clear cache (when needed) without the protected member
|
|
589
|
+
# pylint: disable=protected-access
|
|
590
|
+
current_thresholds = dict(zip(self._threshold_ids, thresholds))
|
|
591
|
+
assert visualization_update >= 0 # Need the input to trigger callback
|
|
592
|
+
assert mass_unit_update >= 0 # These are just to silence pylint
|
|
593
|
+
self._visualization_info = process_visualization_info(
|
|
594
|
+
attribute,
|
|
595
|
+
current_thresholds,
|
|
596
|
+
mass_unit,
|
|
597
|
+
self._visualization_info,
|
|
598
|
+
self._surface_server._image_cache,
|
|
599
|
+
)
|
|
600
|
+
if self._visualization_info["change"]:
|
|
601
|
+
return [], None, no_update
|
|
602
|
+
attribute = MapAttribute(attribute)
|
|
603
|
+
if len(realization) == 0 or ensemble is None:
|
|
604
|
+
raise PreventUpdate
|
|
605
|
+
if isinstance(date, int):
|
|
606
|
+
datestr = self._ensemble_dates(ensemble)[date]
|
|
607
|
+
elif date is None:
|
|
608
|
+
datestr = None
|
|
609
|
+
# Contour data
|
|
610
|
+
contour_data = None
|
|
611
|
+
if MapType[MapAttribute(attribute).name].value == "PLUME":
|
|
612
|
+
contour_data = {
|
|
613
|
+
"property": property_origin(
|
|
614
|
+
attribute, self._map_attribute_names
|
|
615
|
+
),
|
|
616
|
+
"threshold": plume_threshold,
|
|
617
|
+
"smoothing": plume_smoothing,
|
|
618
|
+
}
|
|
619
|
+
# Surface
|
|
620
|
+
surf_data, summed_mass = None, None
|
|
621
|
+
if formation is not None and len(realization) > 0:
|
|
622
|
+
surf_data, summed_mass = SurfaceData.from_server(
|
|
623
|
+
server=self._surface_server,
|
|
624
|
+
provider=self._ensemble_surface_providers[ensemble],
|
|
625
|
+
address=derive_surface_address(
|
|
626
|
+
formation,
|
|
627
|
+
attribute,
|
|
628
|
+
datestr,
|
|
629
|
+
realization,
|
|
630
|
+
self._map_attribute_names,
|
|
631
|
+
statistic,
|
|
632
|
+
contour_data,
|
|
633
|
+
),
|
|
634
|
+
color_map_range=(
|
|
635
|
+
cm_min_val if len(cm_min_auto) == 0 else None,
|
|
636
|
+
cm_max_val if len(cm_max_auto) == 0 else None,
|
|
637
|
+
),
|
|
638
|
+
color_map_name=color_map_name,
|
|
639
|
+
readable_name_=readable_name(attribute),
|
|
640
|
+
visualization_info=self._visualization_info,
|
|
641
|
+
map_attribute_names=self._map_attribute_names,
|
|
642
|
+
)
|
|
643
|
+
assert isinstance(self._visualization_info["unit"], str)
|
|
644
|
+
surf_data, self._summed_co2 = process_summed_mass(
|
|
523
645
|
formation,
|
|
646
|
+
realization,
|
|
524
647
|
datestr,
|
|
525
|
-
|
|
648
|
+
attribute,
|
|
649
|
+
summed_mass,
|
|
650
|
+
surf_data,
|
|
651
|
+
self._summed_co2,
|
|
652
|
+
self._visualization_info["unit"],
|
|
526
653
|
)
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
fault_polygon_url=(
|
|
532
|
-
self._fault_polygon_handlers[ensemble].extract_fault_polygon_url(
|
|
533
|
-
formation,
|
|
654
|
+
plume_polygon = None
|
|
655
|
+
if contour_data is not None:
|
|
656
|
+
plume_polygon = get_plume_polygon(
|
|
657
|
+
self._ensemble_surface_providers[ensemble],
|
|
534
658
|
realization,
|
|
659
|
+
formation,
|
|
660
|
+
datestr,
|
|
661
|
+
contour_data,
|
|
535
662
|
)
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
663
|
+
# Create layers and view bounds
|
|
664
|
+
fault_polygon_url = self._fault_polygon_handlers[
|
|
665
|
+
ensemble
|
|
666
|
+
].extract_fault_polygon_url(formation, realization)
|
|
667
|
+
hazardous_polygon_url = self._polygon_handlers[
|
|
668
|
+
ensemble
|
|
669
|
+
].extract_hazardous_poly_url(realization)
|
|
670
|
+
containment_polygon_url = self._polygon_handlers[
|
|
671
|
+
ensemble
|
|
672
|
+
].extract_containment_poly_url(realization)
|
|
673
|
+
layers = create_map_layers(
|
|
674
|
+
realizations=realization,
|
|
675
|
+
formation=formation,
|
|
676
|
+
surface_data=surf_data,
|
|
677
|
+
fault_polygon_url=fault_polygon_url,
|
|
678
|
+
containment_bounds_url=containment_polygon_url,
|
|
679
|
+
haz_bounds_url=hazardous_polygon_url,
|
|
680
|
+
well_pick_provider=self._well_pick_provider.get(ensemble, None),
|
|
681
|
+
plume_extent_data=plume_polygon,
|
|
682
|
+
options_dialog_options=options_dialog_options,
|
|
683
|
+
selected_wells=selected_wells,
|
|
684
|
+
)
|
|
685
|
+
annotations = create_map_annotations(
|
|
686
|
+
formation=formation,
|
|
687
|
+
surface_data=surf_data,
|
|
688
|
+
colortables=self._color_tables,
|
|
689
|
+
attribute=attribute,
|
|
690
|
+
unit=self._visualization_info["unit"],
|
|
691
|
+
)
|
|
692
|
+
viewports = no_update if current_views else create_map_viewports()
|
|
693
|
+
return layers, annotations, viewports
|
|
694
|
+
|
|
695
|
+
@callback(
|
|
696
|
+
Output(ViewSettings.Ids.OPTIONS_DIALOG, "open"),
|
|
697
|
+
Input(ViewSettings.Ids.OPTIONS_DIALOG_BUTTON, "n_clicks"),
|
|
550
698
|
)
|
|
551
|
-
|
|
552
|
-
|
|
699
|
+
def open_close_options_dialog(_n_clicks: Optional[int]) -> bool:
|
|
700
|
+
if _n_clicks is not None:
|
|
701
|
+
return _n_clicks > 0
|
|
702
|
+
raise PreventUpdate
|
|
553
703
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
704
|
+
@callback(
|
|
705
|
+
Output(ViewSettings.Ids.VISUALIZATION_THRESHOLD_DIALOG, "open"),
|
|
706
|
+
Input(ViewSettings.Ids.VISUALIZATION_THRESHOLD_BUTTON, "n_clicks"),
|
|
707
|
+
)
|
|
708
|
+
def open_close_thresholds(_n_clicks: Optional[int]) -> bool:
|
|
709
|
+
if _n_clicks is not None:
|
|
710
|
+
return _n_clicks > 0
|
|
711
|
+
raise PreventUpdate
|
|
562
712
|
|
|
563
713
|
@callback(
|
|
564
714
|
Output(ViewSettings.Ids.FEEDBACK, "open"),
|
|
@@ -569,42 +719,46 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
569
719
|
return _n_clicks > 0
|
|
570
720
|
raise PreventUpdate
|
|
571
721
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
722
|
+
if self._content["maps"] and self._content["any_table"]:
|
|
723
|
+
|
|
724
|
+
@callback(
|
|
725
|
+
Output(self._view_component(MapViewElement.Ids.TOP_ELEMENT), "style"),
|
|
726
|
+
Output(
|
|
727
|
+
self._view_component(MapViewElement.Ids.BOTTOM_ELEMENT), "style"
|
|
728
|
+
),
|
|
729
|
+
Output(self._view_component(MapViewElement.Ids.BAR_PLOT), "style"),
|
|
730
|
+
Output(self._view_component(MapViewElement.Ids.TIME_PLOT), "style"),
|
|
731
|
+
Output(
|
|
732
|
+
self._view_component(MapViewElement.Ids.STATISTICS_PLOT), "style"
|
|
733
|
+
),
|
|
734
|
+
Input(self._settings_component(ViewSettings.Ids.ENSEMBLE), "value"),
|
|
735
|
+
Input(self._view_component(MapViewElement.Ids.SIZE_SLIDER), "value"),
|
|
736
|
+
State(self._view_component(MapViewElement.Ids.TOP_ELEMENT), "style"),
|
|
737
|
+
State(self._view_component(MapViewElement.Ids.BOTTOM_ELEMENT), "style"),
|
|
738
|
+
Input(self._settings_component(ViewSettings.Ids.GRAPH_SOURCE), "value"),
|
|
739
|
+
)
|
|
740
|
+
def resize_plots(
|
|
741
|
+
ensemble: str,
|
|
742
|
+
slider_value: float,
|
|
743
|
+
top_style: Dict,
|
|
744
|
+
bottom_style: Dict,
|
|
745
|
+
source: GraphSource,
|
|
746
|
+
) -> List[Dict]:
|
|
747
|
+
bottom_style["height"] = f"{slider_value}vh"
|
|
748
|
+
top_style["height"] = f"{80 - slider_value}vh"
|
|
595
749
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
750
|
+
styles = [{"height": f"{slider_value * 0.9 - 4}vh", "width": "90%"}] * 3
|
|
751
|
+
if source == GraphSource.UNSMRY and self._unsmry_providers is None:
|
|
752
|
+
styles = [{"display": "none"}] * 3
|
|
753
|
+
elif (
|
|
754
|
+
source == GraphSource.CONTAINMENT_MASS
|
|
755
|
+
and ensemble not in self._co2_table_providers
|
|
756
|
+
):
|
|
757
|
+
styles = [{"display": "none"}] * 3
|
|
758
|
+
elif (
|
|
759
|
+
source == GraphSource.CONTAINMENT_ACTUAL_VOLUME
|
|
760
|
+
and ensemble not in self._co2_actual_volume_table_providers
|
|
761
|
+
):
|
|
762
|
+
styles = [{"display": "none"}] * 3
|
|
609
763
|
|
|
610
|
-
|
|
764
|
+
return [top_style, bottom_style] + styles
|