webviz-subsurface 0.2.40__py3-none-any.whl → 0.2.42__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.
Files changed (35) hide show
  1. webviz_subsurface/_providers/ensemble_surface_provider/surface_array_server.py +2 -6
  2. webviz_subsurface/_version.py +2 -2
  3. webviz_subsurface/plugins/_co2_migration/__init__.py +1 -0
  4. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_plugin.py +86 -46
  5. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/callbacks.py +53 -30
  6. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/co2volume.py +282 -39
  7. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/color_tables.py +1 -1
  8. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/containment_data_provider.py +6 -4
  9. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/containment_info.py +6 -0
  10. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/ensemble_well_picks.py +1 -1
  11. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/generic.py +59 -6
  12. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/initialization.py +73 -10
  13. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/polygon_handler.py +1 -1
  14. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/summary_graphs.py +20 -18
  15. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/surface_publishing.py +18 -20
  16. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/unsmry_data_provider.py +8 -8
  17. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/views/mainview/mainview.py +98 -44
  18. webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/views/mainview/settings.py +7 -5
  19. webviz_subsurface/plugins/_map_viewer_fmu/layout.py +2 -1
  20. {webviz_subsurface-0.2.40.dist-info → webviz_subsurface-0.2.42.dist-info}/METADATA +3 -3
  21. {webviz_subsurface-0.2.40.dist-info → webviz_subsurface-0.2.42.dist-info}/RECORD +34 -34
  22. {webviz_subsurface-0.2.40.dist-info → webviz_subsurface-0.2.42.dist-info}/entry_points.txt +1 -1
  23. webviz_subsurface/plugins/_co2_leakage/__init__.py +0 -1
  24. /webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_error.py +0 -0
  25. /webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_types.py +0 -0
  26. /webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/__init__.py +0 -0
  27. /webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/_misc.py +0 -0
  28. /webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/fault_polygons_handler.py +0 -0
  29. /webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/_utilities/plume_extent.py +0 -0
  30. /webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/views/__init__.py +0 -0
  31. /webviz_subsurface/plugins/{_co2_leakage → _co2_migration}/views/mainview/__init__.py +0 -0
  32. {webviz_subsurface-0.2.40.dist-info → webviz_subsurface-0.2.42.dist-info}/WHEEL +0 -0
  33. {webviz_subsurface-0.2.40.dist-info → webviz_subsurface-0.2.42.dist-info}/licenses/LICENSE +0 -0
  34. {webviz_subsurface-0.2.40.dist-info → webviz_subsurface-0.2.42.dist-info}/licenses/LICENSE.chromedriver +0 -0
  35. {webviz_subsurface-0.2.40.dist-info → webviz_subsurface-0.2.42.dist-info}/top_level.txt +0 -0
@@ -17,24 +17,26 @@ from webviz_subsurface._providers.ensemble_polygon_provider import PolygonServer
17
17
  from webviz_subsurface._providers.ensemble_surface_provider._surface_discovery import (
18
18
  discover_per_realization_surface_files,
19
19
  )
20
- from webviz_subsurface.plugins._co2_leakage._utilities.containment_data_provider import (
20
+ from webviz_subsurface.plugins._co2_migration._utilities.containment_data_provider import (
21
21
  ContainmentDataProvider,
22
22
  )
23
- from webviz_subsurface.plugins._co2_leakage._utilities.ensemble_well_picks import (
23
+ from webviz_subsurface.plugins._co2_migration._utilities.ensemble_well_picks import (
24
24
  EnsembleWellPicks,
25
25
  )
26
- from webviz_subsurface.plugins._co2_leakage._utilities.generic import (
26
+ from webviz_subsurface.plugins._co2_migration._utilities.generic import (
27
27
  BoundarySettings,
28
28
  FilteredMapAttribute,
29
29
  GraphSource,
30
30
  MapAttribute,
31
31
  MapNamingConvention,
32
+ MapType,
32
33
  MenuOptions,
34
+ PhasesScenario,
33
35
  )
34
- from webviz_subsurface.plugins._co2_leakage._utilities.polygon_handler import (
36
+ from webviz_subsurface.plugins._co2_migration._utilities.polygon_handler import (
35
37
  PolygonHandler,
36
38
  )
37
- from webviz_subsurface.plugins._co2_leakage._utilities.unsmry_data_provider import (
39
+ from webviz_subsurface.plugins._co2_migration._utilities.unsmry_data_provider import (
38
40
  UnsmryDataProvider,
39
41
  )
40
42
 
@@ -46,6 +48,25 @@ LOGGER_TO_SUPPRESS.setLevel(logging.ERROR) # We replace the given warning with
46
48
  WARNING_THRESHOLD_CSV_FILE_SIZE_MB = 100.0
47
49
 
48
50
 
51
+ def resolve_mapattribute_name(
52
+ attr_value: str, scenario: PhasesScenario
53
+ ) -> Optional[str]:
54
+ candidates = [
55
+ name
56
+ for name, member in MapNamingConvention.__members__.items()
57
+ if member.value == attr_value
58
+ ]
59
+ if not candidates:
60
+ return None
61
+ if len(candidates) == 1:
62
+ return candidates[0]
63
+ if scenario == PhasesScenario.THREE_PHASES:
64
+ for m in candidates:
65
+ if m.endswith("3PHASES"):
66
+ return m
67
+ return candidates[0]
68
+
69
+
49
70
  def build_mapping(
50
71
  webviz_settings: WebvizSettings,
51
72
  ensembles: List[str],
@@ -65,12 +86,26 @@ def build_mapping(
65
86
  unique_attributes.update(ens_attr)
66
87
  unique_attributes_list = list(unique_attributes)
67
88
  mapping = {}
89
+ scenario = PhasesScenario.TWO_PHASES
90
+ # NBNB: Solution for Cirrus realizations, not yet clear for Eclipse
91
+ if any("mfs" in item for item in unique_attributes_list):
92
+ scenario = PhasesScenario.THREE_PHASES
68
93
  for attr in unique_attributes_list:
69
- for name_convention in MapNamingConvention:
70
- if attr == name_convention.value:
71
- attribute_key = MapAttribute[name_convention.name].name
72
- mapping[attribute_key] = attr
73
- break
94
+ matched_name = resolve_mapattribute_name(attr, scenario)
95
+ if not matched_name:
96
+ continue
97
+ if scenario == PhasesScenario.THREE_PHASES and any(
98
+ g in attr for g in ["sgas", "amfg"]
99
+ ):
100
+ LOGGER.info(
101
+ f"Map '{attr}' is available, but since the scenario is not saline aquifer,"
102
+ f" neither SGAS nor AMFG are informative about presence of CO2."
103
+ f" If either of these properties is still of interest, they can be"
104
+ f" explicitly requested via 'map_attribute_names' in the config file"
105
+ )
106
+ continue
107
+ attribute_key = MapAttribute[matched_name].name
108
+ mapping[attribute_key] = attr
74
109
  return mapping
75
110
 
76
111
 
@@ -109,6 +144,34 @@ def init_surface_providers(
109
144
  }
110
145
 
111
146
 
147
+ def init_dates_per_ensemble(
148
+ ensembles: List[str],
149
+ attribute_names: FilteredMapAttribute,
150
+ surface_providers: Dict[str, EnsembleSurfaceProvider],
151
+ ) -> Dict[str, List[str]]:
152
+ ensemble_dates: Dict[str, List[str]] = {}
153
+ for ens in ensembles:
154
+ surface_provider = surface_providers[ens]
155
+ dated_attributes = [
156
+ k
157
+ for k in attribute_names.filtered_values
158
+ if MapType[k.name].value != "MIGRATION_TIME"
159
+ ]
160
+ if len(dated_attributes) == 0:
161
+ ensemble_dates[ens] = []
162
+ else:
163
+ date_map_attribute = dated_attributes[0]
164
+ att_name = attribute_names[date_map_attribute]
165
+ dates = surface_provider.surface_dates_for_attribute(att_name)
166
+ if dates is None:
167
+ raise ValueError(
168
+ f"Failed to fetch dates in ensemble {ens} "
169
+ f"for attribute '{att_name}'"
170
+ )
171
+ ensemble_dates[ens] = dates
172
+ return ensemble_dates
173
+
174
+
112
175
  def init_well_pick_provider(
113
176
  ensemble_paths: Dict[str, str],
114
177
  well_pick_path: Optional[str],
@@ -7,7 +7,7 @@ from webviz_subsurface._providers.ensemble_polygon_provider import (
7
7
  from webviz_subsurface._providers.ensemble_polygon_provider.ensemble_polygon_provider import (
8
8
  PolygonsAddress,
9
9
  )
10
- from webviz_subsurface.plugins._co2_leakage._utilities.generic import BoundarySettings
10
+ from webviz_subsurface.plugins._co2_migration._utilities.generic import BoundarySettings
11
11
 
12
12
 
13
13
  class PolygonHandler:
@@ -4,14 +4,14 @@ import numpy as np
4
4
  import plotly.colors
5
5
  import plotly.graph_objects as go
6
6
 
7
- from webviz_subsurface.plugins._co2_leakage._utilities.containment_data_provider import (
7
+ from webviz_subsurface.plugins._co2_migration._utilities.containment_data_provider import (
8
8
  ContainmentDataProvider,
9
9
  )
10
- from webviz_subsurface.plugins._co2_leakage._utilities.generic import (
10
+ from webviz_subsurface.plugins._co2_migration._utilities.generic import (
11
11
  Co2MassScale,
12
12
  Co2VolumeScale,
13
13
  )
14
- from webviz_subsurface.plugins._co2_leakage._utilities.unsmry_data_provider import (
14
+ from webviz_subsurface.plugins._co2_migration._utilities.unsmry_data_provider import (
15
15
  UnsmryDataProvider,
16
16
  )
17
17
 
@@ -33,8 +33,8 @@ def generate_summary_figure(
33
33
  unsmry_last_mobile = df_unsmry[df_unsmry.REAL == r_min][
34
34
  unsmry_provider.colname_mobile
35
35
  ].iloc[-1]
36
- unsmry_last_dissolved = df_unsmry[df_unsmry.REAL == r_min][
37
- unsmry_provider.colname_dissolved
36
+ unsmry_last_dissolved_water = df_unsmry[df_unsmry.REAL == r_min][
37
+ unsmry_provider.colname_dissolved_water
38
38
  ].iloc[-1]
39
39
 
40
40
  containment_reference = df_containment[df_containment.REAL == r_min]
@@ -44,8 +44,8 @@ def generate_summary_figure(
44
44
  containment_last_mobile = containment_reference[
45
45
  containment_reference["phase"] == "free_gas"
46
46
  ]["amount"].iloc[-1]
47
- containment_last_dissolved = containment_reference[
48
- containment_reference["phase"] == "dissolved"
47
+ containment_last_dissolved_water = containment_reference[
48
+ containment_reference["phase"] == "dissolved_water"
49
49
  ]["amount"].iloc[-1]
50
50
  # ---
51
51
  last_total_err_percentage = (
@@ -54,19 +54,21 @@ def generate_summary_figure(
54
54
  last_mobile_err_percentage = (
55
55
  100.0 * abs(containment_last_mobile - unsmry_last_mobile) / unsmry_last_mobile
56
56
  )
57
- last_dissolved_err_percentage = (
57
+ last_dissolved_water_err_percentage = (
58
58
  100.0
59
- * abs(containment_last_dissolved - unsmry_last_dissolved)
60
- / unsmry_last_dissolved
59
+ * abs(containment_last_dissolved_water - unsmry_last_dissolved_water)
60
+ / unsmry_last_dissolved_water
61
61
  )
62
62
  last_total_err_percentage = np.round(last_total_err_percentage, 2)
63
63
  last_mobile_err_percentage = np.round(last_mobile_err_percentage, 2)
64
- last_dissolved_err_percentage = np.round(last_dissolved_err_percentage, 2)
64
+ last_dissolved_water_err_percentage = np.round(
65
+ last_dissolved_water_err_percentage, 2
66
+ )
65
67
 
66
68
  _colors = {
67
69
  "total": plotly.colors.qualitative.Plotly[3],
68
70
  "mobile": plotly.colors.qualitative.Plotly[2],
69
- "dissolved": plotly.colors.qualitative.Plotly[0],
71
+ "dissolved_water": plotly.colors.qualitative.Plotly[0],
70
72
  "trapped": plotly.colors.qualitative.Plotly[1],
71
73
  }
72
74
 
@@ -93,12 +95,12 @@ def generate_summary_figure(
93
95
  )
94
96
  fig.add_scatter(
95
97
  x=sub_df[unsmry_provider.colname_date],
96
- y=sub_df[unsmry_provider.colname_dissolved],
97
- name=f"UNSMRY ({unsmry_provider.colname_dissolved})",
98
- legendgroup="dissolved",
99
- legendgrouptitle_text=f"Dissolved ({last_dissolved_err_percentage} %)",
98
+ y=sub_df[unsmry_provider.colname_dissolved_water],
99
+ name=f"UNSMRY ({unsmry_provider.colname_dissolved_water})",
100
+ legendgroup="dissolved_water",
101
+ legendgrouptitle_text=f"Dissolved in water ({last_dissolved_water_err_percentage} %)",
100
102
  showlegend=showlegend,
101
- marker_color=_colors["dissolved"],
103
+ marker_color=_colors["dissolved_water"],
102
104
  )
103
105
  fig.add_scatter(
104
106
  x=sub_df[unsmry_provider.colname_date],
@@ -114,7 +116,7 @@ def generate_summary_figure(
114
116
  _col_names = {
115
117
  "total": "total",
116
118
  "free_gas": "mobile",
117
- "dissolved": "dissolved",
119
+ "dissolved_water": "dissolved_water",
118
120
  "trapped_gas": "trapped",
119
121
  }
120
122
 
@@ -11,17 +11,17 @@ from webviz_subsurface._providers import (
11
11
  SimulatedSurfaceAddress,
12
12
  StatisticalSurfaceAddress,
13
13
  SurfaceAddress,
14
- SurfaceImageMeta,
15
- SurfaceImageServer,
14
+ SurfaceArrayMeta,
15
+ SurfaceArrayServer,
16
16
  )
17
17
  from webviz_subsurface._providers.ensemble_surface_provider.ensemble_surface_provider import (
18
18
  SurfaceStatistic,
19
19
  )
20
- from webviz_subsurface.plugins._co2_leakage._utilities.generic import (
20
+ from webviz_subsurface.plugins._co2_migration._utilities.generic import (
21
21
  FilteredMapAttribute,
22
22
  MapType,
23
23
  )
24
- from webviz_subsurface.plugins._co2_leakage._utilities.plume_extent import (
24
+ from webviz_subsurface.plugins._co2_migration._utilities.plume_extent import (
25
25
  truncate_surfaces,
26
26
  )
27
27
 
@@ -43,17 +43,17 @@ class TruncatedSurfaceAddress:
43
43
 
44
44
 
45
45
  def publish_and_get_surface_metadata(
46
- server: SurfaceImageServer,
46
+ server: SurfaceArrayServer,
47
47
  provider: EnsembleSurfaceProvider,
48
48
  address: Union[SurfaceAddress, TruncatedSurfaceAddress],
49
49
  visualization_info: Dict[str, Any],
50
50
  map_attribute_names: FilteredMapAttribute,
51
- ) -> Tuple[Optional[SurfaceImageMeta], Optional[str], Optional[Any]]:
51
+ ) -> Tuple[Optional[SurfaceArrayMeta], Optional[str], Optional[Any]]:
52
52
  if isinstance(address, TruncatedSurfaceAddress):
53
- return (
54
- *_publish_and_get_truncated_surface_metadata(server, provider, address),
55
- None,
53
+ meta, partial_url = _publish_and_get_truncated_surface_metadata(
54
+ server, provider, address
56
55
  )
56
+ return meta, partial_url, None
57
57
  address_map_attribute = next(
58
58
  (
59
59
  key
@@ -66,14 +66,12 @@ def publish_and_get_surface_metadata(
66
66
  if MapType[address_map_attribute.name].value == "MIGRATION_TIME" and isinstance(
67
67
  address, StatisticalSurfaceAddress
68
68
  ):
69
- return (
70
- *_publish_and_get_statistical_time_surface_metadata(
71
- server,
72
- provider,
73
- address,
74
- ),
75
- None,
69
+ meta, partial_url = _publish_and_get_statistical_time_surface_metadata(
70
+ server,
71
+ provider,
72
+ address,
76
73
  )
74
+ return meta, partial_url, None
77
75
  provider_id: str = provider.provider_id()
78
76
  qualified_address = QualifiedSurfaceAddress(provider_id, address)
79
77
  surf_meta = server.get_surface_metadata(qualified_address)
@@ -105,10 +103,10 @@ def publish_and_get_surface_metadata(
105
103
 
106
104
 
107
105
  def _publish_and_get_truncated_surface_metadata(
108
- server: SurfaceImageServer,
106
+ server: SurfaceArrayServer,
109
107
  provider: EnsembleSurfaceProvider,
110
108
  address: TruncatedSurfaceAddress,
111
- ) -> Tuple[Optional[SurfaceImageMeta], str]:
109
+ ) -> Tuple[Optional[SurfaceArrayMeta], str]:
112
110
  qualified_address = QualifiedSurfaceAddress(
113
111
  provider.provider_id(),
114
112
  # TODO: Should probably use a dedicated address type for this. Statistical surface
@@ -159,10 +157,10 @@ def _generate_surface(
159
157
 
160
158
 
161
159
  def _publish_and_get_statistical_time_surface_metadata(
162
- server: SurfaceImageServer,
160
+ server: SurfaceArrayServer,
163
161
  provider: EnsembleSurfaceProvider,
164
162
  address: StatisticalSurfaceAddress,
165
- ) -> Tuple[Optional[SurfaceImageMeta], str]:
163
+ ) -> Tuple[Optional[SurfaceArrayMeta], str]:
166
164
  qualified_address = QualifiedSurfaceAddress(
167
165
  provider.provider_id(),
168
166
  StatisticalSurfaceAddress(
@@ -3,13 +3,13 @@ from typing import Tuple, Union
3
3
  import pandas as pd
4
4
 
5
5
  from webviz_subsurface._providers import EnsembleTableProvider
6
- from webviz_subsurface.plugins._co2_leakage._utilities.generic import (
6
+ from webviz_subsurface.plugins._co2_migration._utilities.generic import (
7
7
  Co2MassScale,
8
8
  Co2VolumeScale,
9
9
  MenuOptions,
10
10
  )
11
11
 
12
- _PFLOTRAN_COLNAMES = ("DATE", "FGMDS", "FGMTR", "FGMGP")
12
+ _PFLOTRAN_COLNAMES = ("DATE", "FGMDS", "FGMTR", "FGMMO")
13
13
  _ECLIPSE_COLNAMES = ("DATE", "FWCD", "FGCDI", "FGCDM")
14
14
 
15
15
 
@@ -23,7 +23,7 @@ class UnsmryDataProvider:
23
23
  self._provider = provider
24
24
  (
25
25
  self._colname_date,
26
- self._colname_dissolved,
26
+ self._colname_dissolved_water,
27
27
  self._colname_trapped,
28
28
  self._colname_mobile,
29
29
  ) = UnsmryDataProvider._column_subset_unsmry(provider)
@@ -34,7 +34,7 @@ class UnsmryDataProvider:
34
34
  return {
35
35
  "zones": [],
36
36
  "regions": [],
37
- "phases": ["total", "gas", "dissolved"],
37
+ "phases": ["total", "gas", "dissolved_water"], ##NB: Split gas?
38
38
  "plume_groups": [],
39
39
  "dates": [],
40
40
  }
@@ -44,8 +44,8 @@ class UnsmryDataProvider:
44
44
  return self._colname_date
45
45
 
46
46
  @property
47
- def colname_dissolved(self) -> str:
48
- return self._colname_dissolved
47
+ def colname_dissolved_water(self) -> str:
48
+ return self._colname_dissolved_water
49
49
 
50
50
  @property
51
51
  def colname_trapped(self) -> str:
@@ -62,7 +62,7 @@ class UnsmryDataProvider:
62
62
  def extract(self, scale: Union[Co2MassScale, Co2VolumeScale]) -> pd.DataFrame:
63
63
  columns = [
64
64
  self._colname_date,
65
- self._colname_dissolved,
65
+ self._colname_dissolved_water,
66
66
  self._colname_trapped,
67
67
  self._colname_mobile,
68
68
  ]
@@ -73,7 +73,7 @@ class UnsmryDataProvider:
73
73
  ]
74
74
  )
75
75
  full[self._colname_total] = (
76
- full[self._colname_dissolved]
76
+ full[self._colname_dissolved_water]
77
77
  + full[self._colname_trapped]
78
78
  + full[self.colname_mobile]
79
79
  )
@@ -8,7 +8,10 @@ from webviz_config.utils import StrEnum
8
8
  from webviz_config.webviz_plugin_subclasses import ViewABC, ViewElementABC
9
9
  from webviz_subsurface_components import SubsurfaceViewer
10
10
 
11
- from webviz_subsurface.plugins._co2_leakage._types import LegendData
11
+ from webviz_subsurface.plugins._co2_migration._types import LegendData
12
+ from webviz_subsurface.plugins._co2_migration._utilities.containment_info import (
13
+ MainTabOption,
14
+ )
12
15
 
13
16
 
14
17
  class MainView(ViewABC):
@@ -35,6 +38,9 @@ class MapViewElement(ViewElementABC):
35
38
  TOP_ELEMENT = "top-element"
36
39
  BOTTOM_ELEMENT = "bottom-element"
37
40
  LEGEND_DATA_STORE = "legend-data-store"
41
+ SUMMARY_TABS = "summary-tabs"
42
+ CSV_EXPORT_BUTTON = "csv-export-button"
43
+ DOWNLOAD_CSV = "download-csv"
38
44
 
39
45
  def __init__(
40
46
  self, color_scales: List[Dict[str, Any]], content: Dict[str, bool]
@@ -105,6 +111,15 @@ class MapViewElement(ViewElementABC):
105
111
  self.register_component_unique_id(
106
112
  self.Ids.STATISTICS_PLOT
107
113
  ),
114
+ self.register_component_unique_id(
115
+ self.Ids.CSV_EXPORT_BUTTON
116
+ ),
117
+ self.register_component_unique_id(
118
+ self.Ids.DOWNLOAD_CSV
119
+ ),
120
+ self.register_component_unique_id(
121
+ self.Ids.SUMMARY_TABS
122
+ ),
108
123
  )
109
124
  ),
110
125
  ],
@@ -157,57 +172,96 @@ def _summary_graph_layout(
157
172
  bar_plot_id: str,
158
173
  time_plot_id: str,
159
174
  statistics_plot_id: str,
175
+ csv_export_button_id: str,
176
+ download_csv_id: str,
177
+ summary_tabs_id: str,
160
178
  ) -> List:
161
179
  return [
162
- wcc.Tabs(
163
- id="TAB",
164
- value="tab-1",
165
- children=[
166
- wcc.Tab(
167
- label="Containment state",
168
- value="tab-1",
169
- children=[
170
- html.Div(
171
- wcc.Graph(
172
- id=bar_plot_id,
173
- figure=go.Figure(),
174
- config={
175
- "displayModeBar": False,
176
- },
177
- ),
178
- ),
179
- ],
180
+ html.Div(
181
+ [
182
+ html.Button(
183
+ "↓",
184
+ id=csv_export_button_id,
185
+ title="Export data in current plot to a CSV file",
186
+ style={
187
+ "position": "absolute",
188
+ "bottom": "5px",
189
+ "right": "5px",
190
+ "backgroundColor": "#F4F4F4",
191
+ "border": "1px solid #B0B0B0",
192
+ "color": "#606060",
193
+ "padding": "0",
194
+ "borderRadius": "4px",
195
+ "zIndex": "1000", # Make sure it appears on top
196
+ "fontSize": "18px",
197
+ "fontWeight": "bold",
198
+ "display": "flex",
199
+ "alignItems": "center", # Vertical centering
200
+ "justifyContent": "center", # Horizontal centering
201
+ "lineHeight": "1", # Prevents extra line spacing
202
+ "textAlign": "center",
203
+ "width": "32px",
204
+ "height": "32px",
205
+ "fontFamily": "Arial, sans-serif",
206
+ },
180
207
  ),
181
- wcc.Tab(
182
- label="Containment over time",
183
- value="tab-2",
208
+ wcc.Tabs(
209
+ id=summary_tabs_id,
210
+ value=MainTabOption.CONTAINMENT_STATE,
184
211
  children=[
185
- html.Div(
186
- wcc.Graph(
187
- id=time_plot_id,
188
- figure=go.Figure(),
189
- config={
190
- "displayModeBar": False,
191
- },
192
- ),
212
+ wcc.Tab(
213
+ label="Containment state",
214
+ value=MainTabOption.CONTAINMENT_STATE,
215
+ children=[
216
+ html.Div(
217
+ wcc.Graph(
218
+ id=bar_plot_id,
219
+ figure=go.Figure(),
220
+ config={
221
+ "displayModeBar": False,
222
+ },
223
+ ),
224
+ ),
225
+ ],
193
226
  ),
194
- ],
195
- ),
196
- wcc.Tab(
197
- label="Statistics",
198
- value="tab-3",
199
- children=[
200
- html.Div(
201
- wcc.Graph(
202
- id=statistics_plot_id,
203
- figure=go.Figure(),
204
- config={
205
- "displayModeBar": False,
206
- },
207
- ),
227
+ wcc.Tab(
228
+ label="Containment over time",
229
+ value=MainTabOption.CONTAINMENT_OVER_TIME,
230
+ children=[
231
+ html.Div(
232
+ wcc.Graph(
233
+ id=time_plot_id,
234
+ figure=go.Figure(),
235
+ config={
236
+ "displayModeBar": False,
237
+ },
238
+ ),
239
+ ),
240
+ ],
241
+ ),
242
+ wcc.Tab(
243
+ label="Statistics",
244
+ value=MainTabOption.STATISTICS,
245
+ children=[
246
+ html.Div(
247
+ wcc.Graph(
248
+ id=statistics_plot_id,
249
+ figure=go.Figure(),
250
+ config={
251
+ "displayModeBar": False,
252
+ },
253
+ ),
254
+ ),
255
+ ],
208
256
  ),
209
257
  ],
210
258
  ),
211
259
  ],
260
+ style={
261
+ "position": "relative",
262
+ "height": "100%",
263
+ "width": "100%",
264
+ },
212
265
  ),
266
+ dcc.Download(id=download_csv_id),
213
267
  ]
@@ -12,11 +12,13 @@ from webviz_subsurface._providers.ensemble_surface_provider.ensemble_surface_pro
12
12
  EnsembleSurfaceProvider,
13
13
  SurfaceStatistic,
14
14
  )
15
- from webviz_subsurface.plugins._co2_leakage._utilities.callbacks import property_origin
16
- from webviz_subsurface.plugins._co2_leakage._utilities.containment_info import (
15
+ from webviz_subsurface.plugins._co2_migration._utilities.callbacks import (
16
+ property_origin,
17
+ )
18
+ from webviz_subsurface.plugins._co2_migration._utilities.containment_info import (
17
19
  StatisticsTabOption,
18
20
  )
19
- from webviz_subsurface.plugins._co2_leakage._utilities.generic import (
21
+ from webviz_subsurface.plugins._co2_migration._utilities.generic import (
20
22
  Co2MassScale,
21
23
  Co2VolumeScale,
22
24
  FilteredMapAttribute,
@@ -1350,13 +1352,13 @@ class FeedbackLayout(wcc.Dialog):
1350
1352
  open=False,
1351
1353
  children=[
1352
1354
  dcc.Markdown(
1353
- """If you have any feedback regarding the CO2-Leakage application,
1355
+ """If you have any feedback regarding the CO2-Migration application,
1354
1356
  don't hesitate to"""
1355
1357
  ),
1356
1358
  dcc.Link(
1357
1359
  ["send an email!"],
1358
1360
  href=f"mailto:{get_emails()}&subject=Feedback regarding the "
1359
- f"CO2-Leakage application",
1361
+ f"CO2-Migration application",
1360
1362
  target="_blank",
1361
1363
  style={"float": "left"},
1362
1364
  ),
@@ -810,7 +810,7 @@ def update_map_layers(
810
810
  "name": LayerNames.FAULTPOLYGONS,
811
811
  "id": f"{LayoutElements.FAULTPOLYGONS_LAYER}-{idx}",
812
812
  "visible": visible_fault_polygons_layer,
813
- "parameters": {"depthTest": False},
813
+ "depthTest": False,
814
814
  }
815
815
  )
816
816
  layers.append(
@@ -818,6 +818,7 @@ def update_map_layers(
818
818
  "@@type": LayerTypes.FIELD_OUTLINE,
819
819
  "id": f"{LayoutElements.FIELD_OUTLINE_LAYER}-{idx}",
820
820
  "data": {"type": "FeatureCollection", "features": []},
821
+ "parameters": {"depthTest": False},
821
822
  }
822
823
  )
823
824
  if include_well_layer:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webviz-subsurface
3
- Version: 0.2.40
3
+ Version: 0.2.42
4
4
  Summary: Webviz config plugins for subsurface data
5
5
  Author: R&T Equinor
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -712,8 +712,8 @@ Requires-Dist: pillow>=6.1
712
712
  Requires-Dist: pyarrow>=5.0.0
713
713
  Requires-Dist: pyjwt>=2.6.0
714
714
  Requires-Dist: pyscal>=0.7.5
715
- Requires-Dist: scipy>=1.2
716
- Requires-Dist: statsmodels>=0.12.1
715
+ Requires-Dist: scipy>=1.16
716
+ Requires-Dist: statsmodels>=0.14.5
717
717
  Requires-Dist: xtgeo>=2.20.0
718
718
  Requires-Dist: vtk>=9.2.2
719
719
  Requires-Dist: webviz-config>=0.6.5