webviz-subsurface 0.2.39__py3-none-any.whl → 0.2.41__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/_figures/timeseries_figure.py +1 -1
- webviz_subsurface/_providers/ensemble_summary_provider/_provider_impl_arrow_lazy.py +3 -1
- webviz_subsurface/_providers/ensemble_summary_provider/_provider_impl_arrow_presampled.py +3 -1
- webviz_subsurface/_providers/ensemble_table_provider/ensemble_table_provider_impl_arrow.py +3 -1
- webviz_subsurface/_utils/dataframe_utils.py +1 -1
- webviz_subsurface/_version.py +34 -0
- webviz_subsurface/plugins/_bhp_qc/views/_view_functions.py +5 -5
- webviz_subsurface/plugins/_co2_migration/__init__.py +1 -0
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_plugin.py +86 -46
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/callbacks.py +53 -30
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/co2volume.py +283 -40
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/color_tables.py +1 -1
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/containment_data_provider.py +6 -4
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/containment_info.py +6 -0
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/ensemble_well_picks.py +1 -1
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/generic.py +59 -6
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/initialization.py +73 -10
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/polygon_handler.py +1 -1
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/summary_graphs.py +20 -18
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/surface_publishing.py +18 -20
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/unsmry_data_provider.py +8 -8
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/views/mainview/mainview.py +98 -44
- webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/views/mainview/settings.py +7 -5
- webviz_subsurface/plugins/_disk_usage.py +19 -8
- webviz_subsurface/plugins/_line_plotter_fmu/controllers/build_figure.py +4 -4
- webviz_subsurface/plugins/_map_viewer_fmu/layout.py +2 -1
- webviz_subsurface/plugins/_map_viewer_fmu/map_viewer_fmu.py +1 -1
- webviz_subsurface/plugins/_parameter_analysis/_utils/_parameters_model.py +5 -5
- webviz_subsurface/plugins/_property_statistics/property_statistics.py +1 -1
- webviz_subsurface/plugins/_relative_permeability.py +6 -6
- webviz_subsurface/plugins/_reservoir_simulation_timeseries_regional.py +12 -12
- webviz_subsurface/plugins/_running_time_analysis_fmu.py +6 -1
- webviz_subsurface/plugins/_seismic_misfit.py +2 -3
- webviz_subsurface/plugins/_simulation_time_series/_views/_subplot_view/_utils/vector_statistics.py +4 -4
- webviz_subsurface/plugins/_structural_uncertainty/views/intersection_and_map.py +1 -1
- webviz_subsurface/plugins/_swatinit_qc/_business_logic.py +1 -1
- webviz_subsurface-0.2.41.dist-info/METADATA +822 -0
- {webviz_subsurface-0.2.39.dist-info → webviz_subsurface-0.2.41.dist-info}/RECORD +51 -102
- {webviz_subsurface-0.2.39.dist-info → webviz_subsurface-0.2.41.dist-info}/WHEEL +1 -1
- {webviz_subsurface-0.2.39.dist-info → webviz_subsurface-0.2.41.dist-info}/entry_points.txt +1 -1
- {webviz_subsurface-0.2.39.dist-info → webviz_subsurface-0.2.41.dist-info}/top_level.txt +0 -1
- tests/integration_tests/test_parameter_filter.py +0 -28
- tests/integration_tests/test_surface_selector.py +0 -53
- tests/unit_tests/abbreviations_tests/test_reservoir_simulation.py +0 -94
- tests/unit_tests/data_input/__init__.py +0 -0
- tests/unit_tests/data_input/test_calc_from_cumulatives.py +0 -178
- tests/unit_tests/data_input/test_image_processing.py +0 -11
- tests/unit_tests/mocks/__init__.py +0 -0
- tests/unit_tests/mocks/ensemble_summary_provider_dummy.py +0 -67
- tests/unit_tests/model_tests/__init__.py +0 -0
- tests/unit_tests/model_tests/test_ensemble_model.py +0 -176
- tests/unit_tests/model_tests/test_ensemble_set_model.py +0 -105
- tests/unit_tests/model_tests/test_gruptree_model.py +0 -89
- tests/unit_tests/model_tests/test_property_statistics_model.py +0 -42
- tests/unit_tests/model_tests/test_surface_set_model.py +0 -48
- tests/unit_tests/model_tests/test_well_attributes_model.py +0 -110
- tests/unit_tests/model_tests/test_well_set_model.py +0 -70
- tests/unit_tests/plugin_tests/__init__.py +0 -0
- tests/unit_tests/plugin_tests/test_grouptree.py +0 -175
- tests/unit_tests/plugin_tests/test_simulation_time_series/__init__.py +0 -0
- tests/unit_tests/plugin_tests/test_simulation_time_series/mocks/__init__.py +0 -0
- tests/unit_tests/plugin_tests/test_simulation_time_series/mocks/derived_vectors_accessor_ensemble_summary_provider_mock.py +0 -60
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/__init__.py +0 -0
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/test_create_vector_traces_utils.py +0 -530
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/test_dataframe_utils.py +0 -119
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/test_datetime_utils.py +0 -51
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/test_delta_ensemble_utils.py +0 -222
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/test_derived_delta_ensemble_vectors_accessor_impl.py +0 -319
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/test_derived_ensemble_vectors_accessor_impl.py +0 -271
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/test_derived_ensemble_vectors_accessor_utils.py +0 -78
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/test_derived_vector_accessor.py +0 -57
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/test_ensemble_summary_provider_set_utils.py +0 -213
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/test_from_timeseries_cumulatives.py +0 -322
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/test_history_vectors.py +0 -201
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/test_trace_line_shape.py +0 -56
- tests/unit_tests/plugin_tests/test_simulation_time_series/test_utils/test_vector_statistics.py +0 -171
- tests/unit_tests/plugin_tests/test_tornado_data.py +0 -130
- tests/unit_tests/plugin_tests/test_well_completions.py +0 -158
- tests/unit_tests/provider_tests/__init__.py +0 -0
- tests/unit_tests/provider_tests/test_ensemble_summary_provider.py +0 -255
- tests/unit_tests/provider_tests/test_ensemble_summary_provider_impl_arrow_lazy.py +0 -388
- tests/unit_tests/provider_tests/test_ensemble_summary_provider_impl_arrow_presampled.py +0 -160
- tests/unit_tests/provider_tests/test_ensemble_summary_provider_resampling.py +0 -320
- tests/unit_tests/provider_tests/test_ensemble_table_provider.py +0 -190
- tests/unit_tests/utils_tests/__init__.py +0 -0
- tests/unit_tests/utils_tests/test_dataframe_utils.py +0 -281
- tests/unit_tests/utils_tests/test_ensemble_summary_provider_set/__init__.py +0 -0
- tests/unit_tests/utils_tests/test_ensemble_summary_provider_set/test_ensemble_summary_provider_set.py +0 -306
- tests/unit_tests/utils_tests/test_formatting.py +0 -10
- tests/unit_tests/utils_tests/test_simulation_timeseries.py +0 -51
- webviz_subsurface/plugins/_co2_leakage/__init__.py +0 -1
- webviz_subsurface/plugins/_co2_leakage/_utilities/__init__.py +0 -0
- webviz_subsurface/plugins/_co2_leakage/views/__init__.py +0 -0
- webviz_subsurface/plugins/_co2_leakage/views/mainview/__init__.py +0 -0
- webviz_subsurface-0.2.39.dist-info/METADATA +0 -147
- /webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_error.py +0 -0
- /webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_types.py +0 -0
- {tests/integration_tests → webviz_subsurface/plugins/_co2_migration/_utilities}/__init__.py +0 -0
- /webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/_misc.py +0 -0
- /webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/fault_polygons_handler.py +0 -0
- /webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/plume_extent.py +0 -0
- {tests/unit_tests → webviz_subsurface/plugins/_co2_migration/views}/__init__.py +0 -0
- {tests/unit_tests/abbreviations_tests → webviz_subsurface/plugins/_co2_migration/views/mainview}/__init__.py +0 -0
- {webviz_subsurface-0.2.39.dist-info → webviz_subsurface-0.2.41.dist-info/licenses}/LICENSE +0 -0
- {webviz_subsurface-0.2.39.dist-info → webviz_subsurface-0.2.41.dist-info/licenses}/LICENSE.chromedriver +0 -0
|
@@ -160,7 +160,9 @@ class ProviderImplArrowLazy(EnsembleSummaryProvider):
|
|
|
160
160
|
f"{len(unique_column_names)} unique column names"
|
|
161
161
|
)
|
|
162
162
|
|
|
163
|
-
full_table = pa.concat_tables(
|
|
163
|
+
full_table = pa.concat_tables(
|
|
164
|
+
per_real_tables.values(), promote_options="default"
|
|
165
|
+
)
|
|
164
166
|
elapsed.concat_tables_s = timer.lap_s()
|
|
165
167
|
|
|
166
168
|
real_arr = np.empty(full_table.num_rows, np.int32)
|
|
@@ -214,7 +214,9 @@ class ProviderImplArrowPresampled(EnsembleSummaryProvider):
|
|
|
214
214
|
)
|
|
215
215
|
|
|
216
216
|
timer.lap_s()
|
|
217
|
-
full_table = pa.concat_tables(
|
|
217
|
+
full_table = pa.concat_tables(
|
|
218
|
+
per_real_tables.values(), promote_options="default"
|
|
219
|
+
)
|
|
218
220
|
elapsed.concat_tables_s = timer.lap_s()
|
|
219
221
|
|
|
220
222
|
real_arr = np.empty(full_table.num_rows, np.int32)
|
|
@@ -101,7 +101,9 @@ class EnsembleTableProviderImplArrow(EnsembleTableProvider):
|
|
|
101
101
|
f"{len(unique_column_names)} unique column names"
|
|
102
102
|
)
|
|
103
103
|
|
|
104
|
-
full_table = pa.concat_tables(
|
|
104
|
+
full_table = pa.concat_tables(
|
|
105
|
+
per_real_tables.values(), promote_options="default"
|
|
106
|
+
)
|
|
105
107
|
elapsed.concat_tables_s = timer.lap_s()
|
|
106
108
|
|
|
107
109
|
real_arr = np.empty(full_table.num_rows, np.int32)
|
|
@@ -82,7 +82,7 @@ def make_date_column_datetime_object(df: pd.DataFrame) -> None:
|
|
|
82
82
|
# pylint: disable = unidiomatic-typecheck
|
|
83
83
|
if type(sampled_date_value) == pd.Timestamp:
|
|
84
84
|
df["DATE"] = pd.Series(
|
|
85
|
-
df["DATE"].dt.to_pydatetime(), dtype=object, index=df.index
|
|
85
|
+
np.array(df["DATE"].dt.to_pydatetime()), dtype=object, index=df.index
|
|
86
86
|
)
|
|
87
87
|
return None
|
|
88
88
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
TYPE_CHECKING = False
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
from typing import Union
|
|
17
|
+
|
|
18
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
20
|
+
else:
|
|
21
|
+
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
23
|
+
|
|
24
|
+
version: str
|
|
25
|
+
__version__: str
|
|
26
|
+
__version_tuple__: VERSION_TUPLE
|
|
27
|
+
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
30
|
+
|
|
31
|
+
__version__ = version = '0.2.41'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 2, 41)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = None
|
|
@@ -41,15 +41,15 @@ def calc_statistics(df: pd.DataFrame) -> pd.DataFrame:
|
|
|
41
41
|
# Calculate statistics, ignoring NaNs.
|
|
42
42
|
stat_df = (
|
|
43
43
|
df.groupby("ENSEMBLE")
|
|
44
|
-
.agg([
|
|
44
|
+
.agg(["mean", "count", "std", "min", "max", p10, p50, p90])
|
|
45
45
|
.reset_index(drop=True, level="ENSEMBLE")
|
|
46
46
|
)
|
|
47
47
|
# Rename nanmin, nanmax and nanmean to min, max and mean.
|
|
48
48
|
col_stat_label_map = {
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
49
|
+
"min": "min",
|
|
50
|
+
"max": "max",
|
|
51
|
+
"mean": "mean",
|
|
52
|
+
"std": "std",
|
|
53
53
|
"p10": "high_p10",
|
|
54
54
|
"p90": "low_p90",
|
|
55
55
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from ._plugin import CO2Migration
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from datetime import datetime
|
|
2
3
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
3
4
|
|
|
4
5
|
import plotly.graph_objects as go
|
|
@@ -7,14 +8,15 @@ from dash.exceptions import PreventUpdate
|
|
|
7
8
|
from webviz_config import WebvizPluginABC, WebvizSettings
|
|
8
9
|
from webviz_config.utils import StrEnum, callback_typecheck
|
|
9
10
|
|
|
10
|
-
from webviz_subsurface._providers import FaultPolygonsServer,
|
|
11
|
+
from webviz_subsurface._providers import FaultPolygonsServer, SurfaceArrayServer
|
|
11
12
|
from webviz_subsurface._providers.ensemble_polygon_provider import PolygonServer
|
|
12
|
-
from webviz_subsurface.plugins.
|
|
13
|
+
from webviz_subsurface.plugins._co2_migration._utilities.callbacks import (
|
|
13
14
|
SurfaceData,
|
|
14
15
|
create_map_annotations,
|
|
15
16
|
create_map_layers,
|
|
16
17
|
create_map_viewports,
|
|
17
18
|
derive_surface_address,
|
|
19
|
+
export_figure_data_to_csv,
|
|
18
20
|
extract_legendonly,
|
|
19
21
|
generate_containment_figures,
|
|
20
22
|
generate_unsmry_figures,
|
|
@@ -27,10 +29,10 @@ from webviz_subsurface.plugins._co2_leakage._utilities.callbacks import (
|
|
|
27
29
|
readable_name,
|
|
28
30
|
set_plot_ids,
|
|
29
31
|
)
|
|
30
|
-
from webviz_subsurface.plugins.
|
|
32
|
+
from webviz_subsurface.plugins._co2_migration._utilities.fault_polygons_handler import (
|
|
31
33
|
FaultPolygonsHandler,
|
|
32
34
|
)
|
|
33
|
-
from webviz_subsurface.plugins.
|
|
35
|
+
from webviz_subsurface.plugins._co2_migration._utilities.generic import (
|
|
34
36
|
BoundarySettings,
|
|
35
37
|
Co2MassScale,
|
|
36
38
|
Co2VolumeScale,
|
|
@@ -39,8 +41,9 @@ from webviz_subsurface.plugins._co2_leakage._utilities.generic import (
|
|
|
39
41
|
MapThresholds,
|
|
40
42
|
MapType,
|
|
41
43
|
)
|
|
42
|
-
from webviz_subsurface.plugins.
|
|
44
|
+
from webviz_subsurface.plugins._co2_migration._utilities.initialization import (
|
|
43
45
|
init_containment_data_providers,
|
|
46
|
+
init_dates_per_ensemble,
|
|
44
47
|
init_dictionary_of_content,
|
|
45
48
|
init_map_attribute_names,
|
|
46
49
|
init_menu_options,
|
|
@@ -50,24 +53,26 @@ from webviz_subsurface.plugins._co2_leakage._utilities.initialization import (
|
|
|
50
53
|
init_unsmry_data_providers,
|
|
51
54
|
init_well_pick_provider,
|
|
52
55
|
)
|
|
53
|
-
from webviz_subsurface.plugins.
|
|
56
|
+
from webviz_subsurface.plugins._co2_migration.views.mainview.mainview import (
|
|
54
57
|
MainView,
|
|
55
58
|
MapViewElement,
|
|
56
59
|
)
|
|
57
|
-
from webviz_subsurface.plugins.
|
|
60
|
+
from webviz_subsurface.plugins._co2_migration.views.mainview.settings import (
|
|
61
|
+
ViewSettings,
|
|
62
|
+
)
|
|
58
63
|
|
|
59
64
|
from . import _error
|
|
60
65
|
from ._types import LegendData
|
|
61
|
-
from ._utilities.color_tables import
|
|
62
|
-
from ._utilities.containment_info import StatisticsTabOption
|
|
66
|
+
from ._utilities.color_tables import co2migration_color_tables
|
|
67
|
+
from ._utilities.containment_info import MainTabOption, StatisticsTabOption
|
|
63
68
|
|
|
64
69
|
LOGGER = logging.getLogger(__name__)
|
|
65
70
|
TABLES_PATH = "share/results/tables"
|
|
66
71
|
|
|
67
72
|
|
|
68
73
|
# pylint: disable=too-many-instance-attributes
|
|
69
|
-
class
|
|
70
|
-
"""Plugin for analyzing CO2
|
|
74
|
+
class CO2Migration(WebvizPluginABC):
|
|
75
|
+
"""Plugin for analyzing CO2 migration across multiple realizations in an
|
|
71
76
|
FMU ensemble
|
|
72
77
|
|
|
73
78
|
---
|
|
@@ -121,7 +126,7 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
121
126
|
|
|
122
127
|
The following keys are allowed: `MIGRATION_TIME_SGAS, MIGRATION_TIME_AMFG,
|
|
123
128
|
MIGRATION_TIME_XMF2, MAX_SGAS, MAX_AMFG, MAX_XMF2, MAX_SGSTRAND, MAX_SGTRH, MASS,
|
|
124
|
-
|
|
129
|
+
DISSOLVED_WATER, DISSOLVED_OIL, FREE, FREE_GAS, TRAPPED_GAS`
|
|
125
130
|
|
|
126
131
|
Well pick files and fault polygons might name surfaces differently than the ones
|
|
127
132
|
generated by the ccs-scripts workflow. The options
|
|
@@ -184,7 +189,7 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
184
189
|
for ensemble_name in ensembles
|
|
185
190
|
}
|
|
186
191
|
self._realizations_per_ensemble = init_realizations(ensemble_paths)
|
|
187
|
-
self._surface_server =
|
|
192
|
+
self._surface_server = SurfaceArrayServer.instance(app)
|
|
188
193
|
self._polygons_server = FaultPolygonsServer.instance(app)
|
|
189
194
|
self._map_attribute_names = init_map_attribute_names(
|
|
190
195
|
webviz_settings, ensembles, map_attribute_names
|
|
@@ -195,6 +200,10 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
195
200
|
self._ensemble_surface_providers = init_surface_providers(
|
|
196
201
|
webviz_settings, ensembles
|
|
197
202
|
)
|
|
203
|
+
# Dates
|
|
204
|
+
self._ensemble_dates = init_dates_per_ensemble(
|
|
205
|
+
ensembles, self._map_attribute_names, self._ensemble_surface_providers
|
|
206
|
+
)
|
|
198
207
|
# Polygons
|
|
199
208
|
self._fault_polygon_handlers = {
|
|
200
209
|
ens: FaultPolygonsHandler(
|
|
@@ -251,7 +260,7 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
251
260
|
"change": False,
|
|
252
261
|
"unit": "tons",
|
|
253
262
|
}
|
|
254
|
-
self._color_tables =
|
|
263
|
+
self._color_tables = co2migration_color_tables()
|
|
255
264
|
self._well_pick_names: Dict[str, List[str]] = {
|
|
256
265
|
ens: (
|
|
257
266
|
self._well_pick_provider[ens].well_names
|
|
@@ -296,30 +305,6 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
296
305
|
.to_string()
|
|
297
306
|
)
|
|
298
307
|
|
|
299
|
-
def _ensemble_dates(self, ens: str) -> List[str]:
|
|
300
|
-
surface_provider = self._ensemble_surface_providers[ens]
|
|
301
|
-
date_map_attribute = next(
|
|
302
|
-
(
|
|
303
|
-
k
|
|
304
|
-
for k in self._map_attribute_names.filtered_values
|
|
305
|
-
if MapType[k.name].value != "MIGRATION_TIME"
|
|
306
|
-
),
|
|
307
|
-
None,
|
|
308
|
-
)
|
|
309
|
-
att_name = (
|
|
310
|
-
self._map_attribute_names[date_map_attribute]
|
|
311
|
-
if date_map_attribute is not None
|
|
312
|
-
else None
|
|
313
|
-
)
|
|
314
|
-
dates = (
|
|
315
|
-
None
|
|
316
|
-
if att_name is None
|
|
317
|
-
else surface_provider.surface_dates_for_attribute(att_name)
|
|
318
|
-
)
|
|
319
|
-
if dates is None:
|
|
320
|
-
raise ValueError(f"Failed to fetch dates for attribute '{att_name}'")
|
|
321
|
-
return dates
|
|
322
|
-
|
|
323
308
|
# Might want to do some refactoring if this gets too big
|
|
324
309
|
def _set_callbacks(self) -> None:
|
|
325
310
|
if self._content["any_table"]:
|
|
@@ -327,6 +312,7 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
327
312
|
self._add_legend_change_callback()
|
|
328
313
|
self._add_set_unit_list_callback()
|
|
329
314
|
self._add_time_plot_visibility_callback()
|
|
315
|
+
self._add_csv_export_callback()
|
|
330
316
|
|
|
331
317
|
if self._content["maps"]:
|
|
332
318
|
self._add_set_dates_callback()
|
|
@@ -515,17 +501,17 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
515
501
|
current_thresholds,
|
|
516
502
|
mass_unit,
|
|
517
503
|
self._visualization_info,
|
|
518
|
-
self._surface_server.
|
|
504
|
+
self._surface_server._array_cache,
|
|
519
505
|
)
|
|
520
506
|
if self._visualization_info["change"]:
|
|
521
507
|
return [], None, no_update
|
|
522
508
|
attribute = MapAttribute(attribute)
|
|
523
509
|
if len(realization) == 0 or ensemble is None:
|
|
524
510
|
raise PreventUpdate
|
|
525
|
-
if
|
|
526
|
-
datestr = self._ensemble_dates(ensemble)[date]
|
|
527
|
-
elif date is None:
|
|
511
|
+
if MapType[MapAttribute(attribute).name].value == "MIGRATION_TIME":
|
|
528
512
|
datestr = None
|
|
513
|
+
else:
|
|
514
|
+
datestr = self._ensemble_dates[ensemble][date]
|
|
529
515
|
# Contour data
|
|
530
516
|
contour_data = None
|
|
531
517
|
if MapType[MapAttribute(attribute).name].value == "PLUME":
|
|
@@ -657,13 +643,12 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
657
643
|
if ensemble is None:
|
|
658
644
|
return {}, None
|
|
659
645
|
# Dates
|
|
660
|
-
date_list = self._ensemble_dates(ensemble)
|
|
661
646
|
dates = {
|
|
662
647
|
i: {
|
|
663
648
|
"label": f"{d[:4]}",
|
|
664
649
|
"style": {"writingMode": "vertical-rl"},
|
|
665
650
|
}
|
|
666
|
-
for i, d in enumerate(
|
|
651
|
+
for i, d in enumerate(self._ensemble_dates[ensemble])
|
|
667
652
|
}
|
|
668
653
|
if len(dates.keys()) > 0:
|
|
669
654
|
return dates, max(dates.keys())
|
|
@@ -741,6 +726,7 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
741
726
|
Input(self._settings_component(ViewSettings.Ids.BOX_SHOW_POINTS), "value"),
|
|
742
727
|
)
|
|
743
728
|
@callback_typecheck
|
|
729
|
+
# pylint: disable=too-many-locals
|
|
744
730
|
def update_graphs(
|
|
745
731
|
legend_data: LegendData,
|
|
746
732
|
ensemble: str,
|
|
@@ -763,8 +749,10 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
763
749
|
date_option: str,
|
|
764
750
|
statistics_tab_option: StatisticsTabOption,
|
|
765
751
|
box_show_points: str,
|
|
766
|
-
) -> Tuple[
|
|
767
|
-
|
|
752
|
+
) -> Tuple[go.Figure, go.Figure, go.Figure]:
|
|
753
|
+
if len(realizations) == 0:
|
|
754
|
+
return go.Figure(), go.Figure(), go.Figure()
|
|
755
|
+
|
|
768
756
|
figs = [no_update] * 3
|
|
769
757
|
cont_info = process_containment_info(
|
|
770
758
|
zone,
|
|
@@ -892,3 +880,55 @@ class CO2Leakage(WebvizPluginABC):
|
|
|
892
880
|
if event is None or not isinstance(event, list):
|
|
893
881
|
return False
|
|
894
882
|
return any("visible" in e for e in event if isinstance(e, dict))
|
|
883
|
+
|
|
884
|
+
def _add_csv_export_callback(self) -> None:
|
|
885
|
+
@callback(
|
|
886
|
+
Output(self._view_component(MapViewElement.Ids.DOWNLOAD_CSV), "data"),
|
|
887
|
+
Input(
|
|
888
|
+
self._view_component(MapViewElement.Ids.CSV_EXPORT_BUTTON), "n_clicks"
|
|
889
|
+
),
|
|
890
|
+
State(self._view_component(MapViewElement.Ids.SUMMARY_TABS), "value"),
|
|
891
|
+
State(self._view_component(MapViewElement.Ids.BAR_PLOT), "figure"),
|
|
892
|
+
State(self._view_component(MapViewElement.Ids.TIME_PLOT), "figure"),
|
|
893
|
+
State(self._view_component(MapViewElement.Ids.STATISTICS_PLOT), "figure"),
|
|
894
|
+
State(
|
|
895
|
+
self._settings_component(ViewSettings.Ids.STATISTICS_TAB_OPTION),
|
|
896
|
+
"value",
|
|
897
|
+
),
|
|
898
|
+
prevent_initial_call=True,
|
|
899
|
+
)
|
|
900
|
+
def export_data(
|
|
901
|
+
_n_clicks: int,
|
|
902
|
+
active_tab: str,
|
|
903
|
+
bar_figure: go.Figure,
|
|
904
|
+
time_figure: go.Figure,
|
|
905
|
+
stats_figure: go.Figure,
|
|
906
|
+
statistics_tab_option: StatisticsTabOption,
|
|
907
|
+
) -> Dict[str, Any]:
|
|
908
|
+
file_name = "co2_migration"
|
|
909
|
+
if active_tab == MainTabOption.CONTAINMENT_STATE:
|
|
910
|
+
current_figure = bar_figure
|
|
911
|
+
file_name += "_state_plot"
|
|
912
|
+
plot_choice = "containment_state"
|
|
913
|
+
elif active_tab == MainTabOption.CONTAINMENT_OVER_TIME:
|
|
914
|
+
current_figure = time_figure
|
|
915
|
+
file_name += "_time_plot"
|
|
916
|
+
plot_choice = "containment_time"
|
|
917
|
+
elif active_tab == MainTabOption.STATISTICS:
|
|
918
|
+
current_figure = stats_figure
|
|
919
|
+
if statistics_tab_option == StatisticsTabOption.PROBABILITY_PLOT:
|
|
920
|
+
file_name += "_prob_plot"
|
|
921
|
+
plot_choice = "probability"
|
|
922
|
+
else: # => StatisticsTabOption.BOX_PLOT:
|
|
923
|
+
file_name += "_box_plot"
|
|
924
|
+
plot_choice = "box"
|
|
925
|
+
else:
|
|
926
|
+
raise PreventUpdate # Should not happen
|
|
927
|
+
|
|
928
|
+
date_and_time = datetime.now().strftime("%y%m%d_%H%M%S")
|
|
929
|
+
file_name += f"_{date_and_time}.csv"
|
|
930
|
+
result = export_figure_data_to_csv(current_figure, file_name, plot_choice)
|
|
931
|
+
|
|
932
|
+
if result is None:
|
|
933
|
+
raise PreventUpdate
|
|
934
|
+
return result
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
import warnings
|
|
2
3
|
from dataclasses import dataclass
|
|
3
4
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
@@ -6,7 +7,7 @@ import geojson
|
|
|
6
7
|
import numpy as np
|
|
7
8
|
import plotly.graph_objects as go
|
|
8
9
|
import webviz_subsurface_components as wsc
|
|
9
|
-
from dash import no_update
|
|
10
|
+
from dash import dcc, no_update
|
|
10
11
|
from flask_caching import Cache
|
|
11
12
|
|
|
12
13
|
from webviz_subsurface._providers import (
|
|
@@ -14,32 +15,33 @@ from webviz_subsurface._providers import (
|
|
|
14
15
|
SimulatedSurfaceAddress,
|
|
15
16
|
StatisticalSurfaceAddress,
|
|
16
17
|
SurfaceAddress,
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
SurfaceArrayMeta,
|
|
19
|
+
SurfaceArrayServer,
|
|
19
20
|
)
|
|
20
21
|
from webviz_subsurface._providers.ensemble_surface_provider.ensemble_surface_provider import (
|
|
21
22
|
SurfaceStatistic,
|
|
22
23
|
)
|
|
23
|
-
from webviz_subsurface.plugins.
|
|
24
|
-
from webviz_subsurface.plugins.
|
|
25
|
-
from webviz_subsurface.plugins.
|
|
24
|
+
from webviz_subsurface.plugins._co2_migration._types import LegendData
|
|
25
|
+
from webviz_subsurface.plugins._co2_migration._utilities import plume_extent
|
|
26
|
+
from webviz_subsurface.plugins._co2_migration._utilities.co2volume import (
|
|
27
|
+
extract_df_from_fig,
|
|
26
28
|
generate_co2_box_plot_figure,
|
|
27
29
|
generate_co2_statistics_figure,
|
|
28
30
|
generate_co2_time_containment_figure,
|
|
29
31
|
generate_co2_time_containment_one_realization_figure,
|
|
30
32
|
generate_co2_volume_figure,
|
|
31
33
|
)
|
|
32
|
-
from webviz_subsurface.plugins.
|
|
34
|
+
from webviz_subsurface.plugins._co2_migration._utilities.containment_data_provider import (
|
|
33
35
|
ContainmentDataProvider,
|
|
34
36
|
)
|
|
35
|
-
from webviz_subsurface.plugins.
|
|
37
|
+
from webviz_subsurface.plugins._co2_migration._utilities.containment_info import (
|
|
36
38
|
ContainmentInfo,
|
|
37
39
|
StatisticsTabOption,
|
|
38
40
|
)
|
|
39
|
-
from webviz_subsurface.plugins.
|
|
41
|
+
from webviz_subsurface.plugins._co2_migration._utilities.ensemble_well_picks import (
|
|
40
42
|
EnsembleWellPicks,
|
|
41
43
|
)
|
|
42
|
-
from webviz_subsurface.plugins.
|
|
44
|
+
from webviz_subsurface.plugins._co2_migration._utilities.generic import (
|
|
43
45
|
Co2MassScale,
|
|
44
46
|
Co2VolumeScale,
|
|
45
47
|
FilteredMapAttribute,
|
|
@@ -50,17 +52,19 @@ from webviz_subsurface.plugins._co2_leakage._utilities.generic import (
|
|
|
50
52
|
MapType,
|
|
51
53
|
MenuOptions,
|
|
52
54
|
)
|
|
53
|
-
from webviz_subsurface.plugins.
|
|
55
|
+
from webviz_subsurface.plugins._co2_migration._utilities.summary_graphs import (
|
|
54
56
|
generate_summary_figure,
|
|
55
57
|
)
|
|
56
|
-
from webviz_subsurface.plugins.
|
|
58
|
+
from webviz_subsurface.plugins._co2_migration._utilities.surface_publishing import (
|
|
57
59
|
TruncatedSurfaceAddress,
|
|
58
60
|
publish_and_get_surface_metadata,
|
|
59
61
|
)
|
|
60
|
-
from webviz_subsurface.plugins.
|
|
62
|
+
from webviz_subsurface.plugins._co2_migration._utilities.unsmry_data_provider import (
|
|
61
63
|
UnsmryDataProvider,
|
|
62
64
|
)
|
|
63
65
|
|
|
66
|
+
LOGGER = logging.getLogger(__name__)
|
|
67
|
+
|
|
64
68
|
|
|
65
69
|
def property_origin(
|
|
66
70
|
attribute: MapAttribute, map_attribute_names: FilteredMapAttribute
|
|
@@ -81,12 +85,12 @@ class SurfaceData:
|
|
|
81
85
|
color_map_range: Tuple[Optional[float], Optional[float]]
|
|
82
86
|
color_map_name: str
|
|
83
87
|
value_range: Tuple[float, float]
|
|
84
|
-
meta_data:
|
|
88
|
+
meta_data: SurfaceArrayMeta
|
|
85
89
|
img_url: str
|
|
86
90
|
|
|
87
91
|
@staticmethod
|
|
88
92
|
def from_server(
|
|
89
|
-
server:
|
|
93
|
+
server: SurfaceArrayServer,
|
|
90
94
|
provider: EnsembleSurfaceProvider,
|
|
91
95
|
address: Union[SurfaceAddress, TruncatedSurfaceAddress],
|
|
92
96
|
color_map_range: Tuple[Optional[float], Optional[float]],
|
|
@@ -158,11 +162,6 @@ def derive_surface_address(
|
|
|
158
162
|
threshold=contour_data["threshold"] if contour_data else 0.0,
|
|
159
163
|
smoothing=contour_data["smoothing"] if contour_data else 0.0,
|
|
160
164
|
)
|
|
161
|
-
date = (
|
|
162
|
-
None
|
|
163
|
-
if MapType[MapAttribute(attribute).name].value == "MIGRATION_TIME"
|
|
164
|
-
else date
|
|
165
|
-
)
|
|
166
165
|
if len(realization) == 1:
|
|
167
166
|
return SimulatedSurfaceAddress(
|
|
168
167
|
attribute=map_attribute_names[attribute],
|
|
@@ -192,7 +191,7 @@ def get_plume_polygon(
|
|
|
192
191
|
surface_provider: EnsembleSurfaceProvider,
|
|
193
192
|
realizations: List[int],
|
|
194
193
|
surface_name: str,
|
|
195
|
-
datestr: str,
|
|
194
|
+
datestr: Optional[str],
|
|
196
195
|
contour_data: Dict[str, Any],
|
|
197
196
|
) -> Optional[geojson.FeatureCollection]:
|
|
198
197
|
surface_attribute = contour_data["property"]
|
|
@@ -312,17 +311,22 @@ def create_map_layers(
|
|
|
312
311
|
layers = []
|
|
313
312
|
if surface_data is not None:
|
|
314
313
|
# Update ColormapLayer
|
|
314
|
+
meta = surface_data.meta_data
|
|
315
315
|
layers.append(
|
|
316
316
|
{
|
|
317
|
-
"@@type": "
|
|
318
|
-
"name": surface_data.readable_name,
|
|
317
|
+
"@@type": "MapLayer",
|
|
319
318
|
"id": "colormap-layer",
|
|
320
|
-
"
|
|
321
|
-
"
|
|
322
|
-
"
|
|
323
|
-
|
|
319
|
+
"name": surface_data.readable_name,
|
|
320
|
+
"meshUrl": surface_data.img_url,
|
|
321
|
+
"frame": {
|
|
322
|
+
"origin": [meta.x_ori, meta.y_ori],
|
|
323
|
+
"count": [meta.x_count, meta.y_count],
|
|
324
|
+
"increment": [meta.x_inc, meta.y_inc],
|
|
325
|
+
"rotDeg": meta.rot_deg,
|
|
326
|
+
},
|
|
324
327
|
"colorMapName": surface_data.color_map_name,
|
|
325
|
-
"
|
|
328
|
+
"colorMapRange": surface_data.color_map_range,
|
|
329
|
+
"material": False,
|
|
326
330
|
}
|
|
327
331
|
)
|
|
328
332
|
|
|
@@ -408,7 +412,7 @@ def generate_containment_figures(
|
|
|
408
412
|
try:
|
|
409
413
|
fig0 = generate_co2_volume_figure(
|
|
410
414
|
table_provider,
|
|
411
|
-
|
|
415
|
+
realizations,
|
|
412
416
|
co2_scale,
|
|
413
417
|
containment_info,
|
|
414
418
|
legenddata["bar_legendonly"],
|
|
@@ -624,7 +628,7 @@ def set_plot_ids(
|
|
|
624
628
|
def process_summed_mass(
|
|
625
629
|
formation: str,
|
|
626
630
|
realization: List[int],
|
|
627
|
-
datestr: str,
|
|
631
|
+
datestr: Optional[str],
|
|
628
632
|
attribute: MapAttribute,
|
|
629
633
|
summed_mass: Optional[float],
|
|
630
634
|
surf_data: Optional[SurfaceData],
|
|
@@ -641,3 +645,22 @@ def process_summed_mass(
|
|
|
641
645
|
f" ({unit}) (Total: {summed_co2[summed_co2_key]:.2E}): "
|
|
642
646
|
)
|
|
643
647
|
return surf_data, summed_co2
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
def export_figure_data_to_csv(
|
|
651
|
+
figure: Dict, file_name: str, plot_choice: str
|
|
652
|
+
) -> Optional[Dict[str, Any]]:
|
|
653
|
+
"""Export visible figure data to CSV file"""
|
|
654
|
+
try:
|
|
655
|
+
figure_go = go.Figure(figure) # Dash State returns dict
|
|
656
|
+
df = extract_df_from_fig(figure_go.data, plot_choice)
|
|
657
|
+
if df.empty:
|
|
658
|
+
LOGGER.warning("No plot data to export to CSV file.")
|
|
659
|
+
return None
|
|
660
|
+
|
|
661
|
+
result = dcc.send_data_frame(df.to_csv, filename=file_name, index=False)
|
|
662
|
+
return result
|
|
663
|
+
|
|
664
|
+
except (ValueError, KeyError, AttributeError, TypeError) as e:
|
|
665
|
+
LOGGER.warning(f"Failed to export plot data to CSV file: {e}")
|
|
666
|
+
return None
|