webviz-subsurface 0.2.36__py3-none-any.whl → 0.2.38__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/_datainput/well_completions.py +2 -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 +577 -293
- webviz_subsurface/plugins/_co2_leakage/_types.py +7 -0
- webviz_subsurface/plugins/_co2_leakage/_utilities/_misc.py +9 -0
- webviz_subsurface/plugins/_co2_leakage/_utilities/callbacks.py +226 -186
- webviz_subsurface/plugins/_co2_leakage/_utilities/co2volume.py +591 -128
- webviz_subsurface/plugins/_co2_leakage/_utilities/containment_data_provider.py +147 -0
- webviz_subsurface/plugins/_co2_leakage/_utilities/containment_info.py +31 -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 +199 -97
- 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 +122 -21
- webviz_subsurface/plugins/_co2_leakage/_utilities/unsmry_data_provider.py +108 -0
- webviz_subsurface/plugins/_co2_leakage/views/mainview/mainview.py +44 -19
- webviz_subsurface/plugins/_co2_leakage/views/mainview/settings.py +944 -359
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.38.dist-info}/METADATA +2 -2
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.38.dist-info}/RECORD +33 -20
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.38.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.38.dist-info}/LICENSE +0 -0
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.38.dist-info}/LICENSE.chromedriver +0 -0
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.38.dist-info}/entry_points.txt +0 -0
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.38.dist-info}/top_level.txt +0 -0
|
@@ -13,12 +13,22 @@ from webviz_subsurface._providers.ensemble_surface_provider.ensemble_surface_pro
|
|
|
13
13
|
SurfaceStatistic,
|
|
14
14
|
)
|
|
15
15
|
from webviz_subsurface.plugins._co2_leakage._utilities.callbacks import property_origin
|
|
16
|
+
from webviz_subsurface.plugins._co2_leakage._utilities.containment_info import (
|
|
17
|
+
StatisticsTabOption,
|
|
18
|
+
)
|
|
16
19
|
from webviz_subsurface.plugins._co2_leakage._utilities.generic import (
|
|
17
20
|
Co2MassScale,
|
|
21
|
+
Co2VolumeScale,
|
|
22
|
+
FilteredMapAttribute,
|
|
18
23
|
GraphSource,
|
|
19
24
|
LayoutLabels,
|
|
20
25
|
LayoutStyle,
|
|
21
26
|
MapAttribute,
|
|
27
|
+
MapGroup,
|
|
28
|
+
MapThresholds,
|
|
29
|
+
MapType,
|
|
30
|
+
MenuOptions,
|
|
31
|
+
map_group_labels,
|
|
22
32
|
)
|
|
23
33
|
|
|
24
34
|
|
|
@@ -33,6 +43,7 @@ class ViewSettings(SettingsGroupABC):
|
|
|
33
43
|
FORMATION = "formation"
|
|
34
44
|
ENSEMBLE = "ensemble"
|
|
35
45
|
REALIZATION = "realization"
|
|
46
|
+
ALL_REAL = "all-realizations"
|
|
36
47
|
|
|
37
48
|
PROPERTY = "property"
|
|
38
49
|
STATISTIC = "statistic"
|
|
@@ -48,6 +59,8 @@ class ViewSettings(SettingsGroupABC):
|
|
|
48
59
|
Y_MAX_GRAPH = "y-max-graph"
|
|
49
60
|
Y_MIN_AUTO_GRAPH = "y-min-auto-graph"
|
|
50
61
|
Y_MAX_AUTO_GRAPH = "y-max-auto-graph"
|
|
62
|
+
Y_LIM_OPTIONS = "y_limit_options"
|
|
63
|
+
REAL_OR_STAT = "realization-or-statistics"
|
|
51
64
|
COLOR_BY = "color-by"
|
|
52
65
|
MARK_BY = "mark-by"
|
|
53
66
|
SORT_PLOT = "sort-plot"
|
|
@@ -59,120 +72,166 @@ class ViewSettings(SettingsGroupABC):
|
|
|
59
72
|
PHASE = "phase"
|
|
60
73
|
PHASE_MENU = "phase-menu"
|
|
61
74
|
CONTAINMENT = "containment"
|
|
75
|
+
PLUME_GROUP = "plume-group"
|
|
62
76
|
CONTAINMENT_MENU = "containment-menu"
|
|
77
|
+
PLUME_GROUP_MENU = "plume-group-menu"
|
|
78
|
+
DATE_OPTION = "date-option"
|
|
79
|
+
DATE_OPTION_COL = "date-option-column"
|
|
80
|
+
STATISTICS_TAB_OPTION = "statistics-tab-option"
|
|
81
|
+
BOX_SHOW_POINTS = "box-plot-points"
|
|
63
82
|
|
|
64
83
|
PLUME_THRESHOLD = "plume-threshold"
|
|
65
84
|
PLUME_SMOOTHING = "plume-smoothing"
|
|
66
85
|
|
|
67
|
-
VISUALIZATION_THRESHOLD = "visualization-threshold"
|
|
68
86
|
VISUALIZATION_UPDATE = "visualization-update"
|
|
87
|
+
VISUALIZATION_THRESHOLD_BUTTON = "visualization-threshold-button"
|
|
88
|
+
VISUALIZATION_THRESHOLD_DIALOG = "visualization-threshold-dialog"
|
|
69
89
|
MASS_UNIT = "mass-unit"
|
|
90
|
+
MASS_UNIT_UPDATE = "mass-unit-update"
|
|
70
91
|
|
|
71
92
|
FEEDBACK_BUTTON = "feedback-button"
|
|
72
93
|
FEEDBACK = "feedback"
|
|
73
94
|
|
|
95
|
+
# pylint: disable=too-many-arguments
|
|
74
96
|
def __init__(
|
|
75
97
|
self,
|
|
76
98
|
ensemble_paths: Dict[str, str],
|
|
99
|
+
realizations_per_ensemble: Dict[str, List[int]],
|
|
77
100
|
ensemble_surface_providers: Dict[str, EnsembleSurfaceProvider],
|
|
78
101
|
initial_surface: Optional[str],
|
|
79
|
-
map_attribute_names:
|
|
102
|
+
map_attribute_names: FilteredMapAttribute,
|
|
103
|
+
map_thresholds: MapThresholds,
|
|
80
104
|
color_scale_names: List[str],
|
|
81
105
|
well_names_dict: Dict[str, List[str]],
|
|
82
|
-
menu_options: Dict[str, Dict[
|
|
106
|
+
menu_options: Dict[str, Dict[GraphSource, MenuOptions]],
|
|
107
|
+
content: Dict[str, bool],
|
|
83
108
|
):
|
|
84
109
|
super().__init__("Settings")
|
|
85
110
|
self._ensemble_paths = ensemble_paths
|
|
111
|
+
self._realizations_per_ensemble = realizations_per_ensemble
|
|
86
112
|
self._ensemble_surface_providers = ensemble_surface_providers
|
|
87
113
|
self._map_attribute_names = map_attribute_names
|
|
114
|
+
self._thresholds = map_thresholds
|
|
115
|
+
self._threshold_ids = list(self._thresholds.standard_thresholds.keys())
|
|
88
116
|
self._color_scale_names = color_scale_names
|
|
89
117
|
self._initial_surface = initial_surface
|
|
90
118
|
self._well_names_dict = well_names_dict
|
|
91
119
|
self._menu_options = menu_options
|
|
92
|
-
self.
|
|
93
|
-
len(inner_dict["zones"]) > 0
|
|
94
|
-
for outer_dict in menu_options.values()
|
|
95
|
-
for inner_dict in outer_dict.values()
|
|
96
|
-
)
|
|
97
|
-
self._has_regions = max(
|
|
98
|
-
len(inner_dict["regions"]) > 0
|
|
99
|
-
for outer_dict in menu_options.values()
|
|
100
|
-
for inner_dict in outer_dict.values()
|
|
101
|
-
)
|
|
120
|
+
self._content = content
|
|
102
121
|
|
|
103
122
|
def layout(self) -> List[Component]:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
123
|
+
menu_layout = []
|
|
124
|
+
if self._content["maps"]:
|
|
125
|
+
menu_layout += [
|
|
126
|
+
DialogLayout(self._well_names_dict, list(self._ensemble_paths.keys())),
|
|
127
|
+
OpenDialogButton(),
|
|
128
|
+
]
|
|
129
|
+
menu_layout.append(
|
|
107
130
|
EnsembleSelectorLayout(
|
|
108
131
|
self.register_component_unique_id(self.Ids.ENSEMBLE),
|
|
109
132
|
self.register_component_unique_id(self.Ids.REALIZATION),
|
|
133
|
+
self.register_component_unique_id(self.Ids.ALL_REAL),
|
|
110
134
|
list(self._ensemble_paths.keys()),
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
self.register_component_unique_id(self.Ids.
|
|
131
|
-
self.register_component_unique_id(self.Ids.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
self.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
self.register_component_unique_id(self.Ids.
|
|
141
|
-
self.register_component_unique_id(self.Ids.
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
if self._content["maps"]:
|
|
138
|
+
menu_layout += [
|
|
139
|
+
FilterSelectorLayout(
|
|
140
|
+
self.register_component_unique_id(self.Ids.FORMATION)
|
|
141
|
+
),
|
|
142
|
+
VisualizationThresholdsLayout(
|
|
143
|
+
self._threshold_ids,
|
|
144
|
+
self._thresholds,
|
|
145
|
+
self.register_component_unique_id(self.Ids.VISUALIZATION_UPDATE),
|
|
146
|
+
),
|
|
147
|
+
MapSelectorLayout(
|
|
148
|
+
self._color_scale_names,
|
|
149
|
+
self.register_component_unique_id(self.Ids.PROPERTY),
|
|
150
|
+
self.register_component_unique_id(self.Ids.STATISTIC),
|
|
151
|
+
self.register_component_unique_id(self.Ids.COLOR_SCALE),
|
|
152
|
+
self.register_component_unique_id(self.Ids.CM_MIN),
|
|
153
|
+
self.register_component_unique_id(self.Ids.CM_MAX),
|
|
154
|
+
self.register_component_unique_id(self.Ids.CM_MIN_AUTO),
|
|
155
|
+
self.register_component_unique_id(self.Ids.CM_MAX_AUTO),
|
|
156
|
+
self.register_component_unique_id(self.Ids.MASS_UNIT),
|
|
157
|
+
self.register_component_unique_id(self.Ids.MASS_UNIT_UPDATE),
|
|
158
|
+
self._map_attribute_names,
|
|
159
|
+
),
|
|
160
|
+
]
|
|
161
|
+
if self._content["any_table"]:
|
|
162
|
+
menu_layout.append(
|
|
163
|
+
GraphSelectorsLayout(
|
|
164
|
+
self.register_component_unique_id(self.Ids.GRAPH_SOURCE),
|
|
165
|
+
self.register_component_unique_id(self.Ids.CO2_SCALE),
|
|
166
|
+
[
|
|
167
|
+
self.register_component_unique_id(self.Ids.Y_MIN_GRAPH),
|
|
168
|
+
self.register_component_unique_id(self.Ids.Y_MIN_AUTO_GRAPH),
|
|
169
|
+
],
|
|
170
|
+
[
|
|
171
|
+
self.register_component_unique_id(self.Ids.Y_MAX_GRAPH),
|
|
172
|
+
self.register_component_unique_id(self.Ids.Y_MAX_AUTO_GRAPH),
|
|
173
|
+
],
|
|
174
|
+
{
|
|
175
|
+
k: self.register_component_unique_id(k)
|
|
176
|
+
for k in [
|
|
177
|
+
self.Ids.COLOR_BY,
|
|
178
|
+
self.Ids.MARK_BY,
|
|
179
|
+
self.Ids.SORT_PLOT,
|
|
180
|
+
self.Ids.ZONE,
|
|
181
|
+
self.Ids.ZONE_COL,
|
|
182
|
+
self.Ids.REGION,
|
|
183
|
+
self.Ids.REGION_COL,
|
|
184
|
+
self.Ids.ZONE_REGION,
|
|
185
|
+
self.Ids.PHASE,
|
|
186
|
+
self.Ids.PHASE_MENU,
|
|
187
|
+
self.Ids.CONTAINMENT,
|
|
188
|
+
self.Ids.CONTAINMENT_MENU,
|
|
189
|
+
self.Ids.PLUME_GROUP,
|
|
190
|
+
self.Ids.PLUME_GROUP_MENU,
|
|
191
|
+
self.Ids.REAL_OR_STAT,
|
|
192
|
+
self.Ids.Y_LIM_OPTIONS,
|
|
193
|
+
self.Ids.DATE_OPTION,
|
|
194
|
+
self.Ids.DATE_OPTION_COL,
|
|
195
|
+
self.Ids.STATISTICS_TAB_OPTION,
|
|
196
|
+
self.Ids.BOX_SHOW_POINTS,
|
|
197
|
+
]
|
|
198
|
+
},
|
|
199
|
+
self._content,
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
if self._content["maps"]:
|
|
203
|
+
menu_layout.append(
|
|
204
|
+
ExperimentalFeaturesLayout(
|
|
205
|
+
self.register_component_unique_id(self.Ids.PLUME_THRESHOLD),
|
|
206
|
+
self.register_component_unique_id(self.Ids.PLUME_SMOOTHING),
|
|
207
|
+
),
|
|
208
|
+
)
|
|
209
|
+
menu_layout += [
|
|
158
210
|
FeedbackLayout(),
|
|
159
211
|
FeedbackButton(),
|
|
160
212
|
]
|
|
213
|
+
return menu_layout
|
|
161
214
|
|
|
215
|
+
# pylint: disable=too-many-statements
|
|
162
216
|
def set_callbacks(self) -> None:
|
|
217
|
+
# pylint: disable=unused-argument
|
|
163
218
|
@callback(
|
|
164
219
|
Output(
|
|
165
220
|
self.component_unique_id(self.Ids.REALIZATION).to_string(), "options"
|
|
166
221
|
),
|
|
167
222
|
Output(self.component_unique_id(self.Ids.REALIZATION).to_string(), "value"),
|
|
168
223
|
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
224
|
+
Input(self.component_unique_id(self.Ids.ALL_REAL).to_string(), "n_clicks"),
|
|
169
225
|
)
|
|
170
|
-
def set_realizations(
|
|
226
|
+
def set_realizations(
|
|
227
|
+
ensemble: str,
|
|
228
|
+
select_all: int,
|
|
229
|
+
) -> Tuple[List[Dict[str, Any]], List[int]]:
|
|
171
230
|
rlz = [
|
|
172
231
|
{"value": r, "label": str(r)}
|
|
173
|
-
for r in self.
|
|
232
|
+
for r in self._realizations_per_ensemble[ensemble]
|
|
174
233
|
]
|
|
175
|
-
return rlz, [
|
|
234
|
+
return rlz, self._realizations_per_ensemble[ensemble] # type: ignore
|
|
176
235
|
|
|
177
236
|
@callback(
|
|
178
237
|
Output(self.component_unique_id(self.Ids.FORMATION).to_string(), "options"),
|
|
@@ -193,10 +252,7 @@ class ViewSettings(SettingsGroupABC):
|
|
|
193
252
|
if len(surfaces) == 0:
|
|
194
253
|
warning = f"Surface not found for property: {prop}.\n"
|
|
195
254
|
warning += f"Expected name: <formation>--{prop_name}"
|
|
196
|
-
if MapAttribute(prop)
|
|
197
|
-
MapAttribute.MIGRATION_TIME_SGAS,
|
|
198
|
-
MapAttribute.MIGRATION_TIME_AMFG,
|
|
199
|
-
]:
|
|
255
|
+
if MapType[MapAttribute(prop).name].value != "MIGRATION_TIME":
|
|
200
256
|
warning += "--<date>"
|
|
201
257
|
warnings.warn(warning + ".gri")
|
|
202
258
|
# Formation names
|
|
@@ -215,181 +271,311 @@ class ViewSettings(SettingsGroupABC):
|
|
|
215
271
|
)
|
|
216
272
|
return formations, picked_formation
|
|
217
273
|
|
|
218
|
-
|
|
219
|
-
Output(
|
|
220
|
-
self.component_unique_id(self.Ids.STATISTIC).to_string(), "disabled"
|
|
221
|
-
),
|
|
222
|
-
Input(self.component_unique_id(self.Ids.REALIZATION).to_string(), "value"),
|
|
223
|
-
Input(self.component_unique_id(self.Ids.PROPERTY).to_string(), "value"),
|
|
224
|
-
)
|
|
225
|
-
def toggle_statistics(realizations: List[int], attribute: str) -> bool:
|
|
226
|
-
if len(realizations) <= 1:
|
|
227
|
-
return True
|
|
228
|
-
if MapAttribute(attribute) in (
|
|
229
|
-
MapAttribute.SGAS_PLUME,
|
|
230
|
-
MapAttribute.AMFG_PLUME,
|
|
231
|
-
):
|
|
232
|
-
return True
|
|
233
|
-
return False
|
|
274
|
+
if self._content["maps"]:
|
|
234
275
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
276
|
+
@callback(
|
|
277
|
+
Output(
|
|
278
|
+
self.component_unique_id(self.Ids.STATISTIC).to_string(), "disabled"
|
|
279
|
+
),
|
|
280
|
+
Input(
|
|
281
|
+
self.component_unique_id(self.Ids.REALIZATION).to_string(), "value"
|
|
282
|
+
),
|
|
283
|
+
Input(self.component_unique_id(self.Ids.PROPERTY).to_string(), "value"),
|
|
284
|
+
)
|
|
285
|
+
def toggle_statistics(realizations: List[int], attribute: str) -> bool:
|
|
286
|
+
if len(realizations) <= 1:
|
|
287
|
+
return True
|
|
288
|
+
if MapType[MapAttribute(attribute).name].value == "PLUME":
|
|
289
|
+
return True
|
|
290
|
+
return False
|
|
245
291
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
292
|
+
@callback(
|
|
293
|
+
Output(
|
|
294
|
+
self.component_unique_id(self.Ids.CM_MIN).to_string(), "disabled"
|
|
295
|
+
),
|
|
296
|
+
Output(
|
|
297
|
+
self.component_unique_id(self.Ids.CM_MAX).to_string(), "disabled"
|
|
298
|
+
),
|
|
299
|
+
Input(
|
|
300
|
+
self.component_unique_id(self.Ids.CM_MIN_AUTO).to_string(), "value"
|
|
301
|
+
),
|
|
302
|
+
Input(
|
|
303
|
+
self.component_unique_id(self.Ids.CM_MAX_AUTO).to_string(), "value"
|
|
304
|
+
),
|
|
305
|
+
)
|
|
306
|
+
def set_color_range_data(
|
|
307
|
+
min_auto: List[str], max_auto: List[str]
|
|
308
|
+
) -> Tuple[bool, bool]:
|
|
309
|
+
return len(min_auto) == 1, len(max_auto) == 1
|
|
258
310
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
Input(
|
|
270
|
-
self.component_unique_id(self.Ids.Y_MAX_AUTO_GRAPH).to_string(), "value"
|
|
271
|
-
),
|
|
272
|
-
)
|
|
273
|
-
def set_y_min_max(
|
|
274
|
-
min_auto: List[str], max_auto: List[str]
|
|
275
|
-
) -> Tuple[bool, bool]:
|
|
276
|
-
return len(min_auto) == 1, len(max_auto) == 1
|
|
311
|
+
@callback(
|
|
312
|
+
Output(
|
|
313
|
+
self.component_unique_id(self.Ids.MASS_UNIT).to_string(), "disabled"
|
|
314
|
+
),
|
|
315
|
+
Input(self.component_unique_id(self.Ids.PROPERTY).to_string(), "value"),
|
|
316
|
+
)
|
|
317
|
+
def toggle_unit(attribute: str) -> bool:
|
|
318
|
+
if MapType[MapAttribute(attribute).name].value != "MASS":
|
|
319
|
+
return True
|
|
320
|
+
return False
|
|
277
321
|
|
|
278
|
-
|
|
279
|
-
Output(self.component_unique_id(self.Ids.PHASE).to_string(), "options"),
|
|
280
|
-
Output(self.component_unique_id(self.Ids.PHASE).to_string(), "value"),
|
|
281
|
-
Input(self.component_unique_id(self.Ids.GRAPH_SOURCE).to_string(), "value"),
|
|
282
|
-
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
283
|
-
State(self.component_unique_id(self.Ids.PHASE).to_string(), "value"),
|
|
284
|
-
)
|
|
285
|
-
def set_phases(
|
|
286
|
-
source: GraphSource,
|
|
287
|
-
ensemble: str,
|
|
288
|
-
current_value: str,
|
|
289
|
-
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
290
|
-
if ensemble is not None:
|
|
291
|
-
phases = self._menu_options[ensemble][source]["phases"]
|
|
292
|
-
options = [{"label": phase.title(), "value": phase} for phase in phases]
|
|
293
|
-
return options, no_update if current_value in phases else "total"
|
|
294
|
-
return [], "total"
|
|
322
|
+
if self._content["any_table"]:
|
|
295
323
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
324
|
+
@callback(
|
|
325
|
+
Output(
|
|
326
|
+
self.component_unique_id(self.Ids.Y_MIN_GRAPH).to_string(),
|
|
327
|
+
"disabled",
|
|
328
|
+
),
|
|
329
|
+
Output(
|
|
330
|
+
self.component_unique_id(self.Ids.Y_MAX_GRAPH).to_string(),
|
|
331
|
+
"disabled",
|
|
332
|
+
),
|
|
333
|
+
Input(
|
|
334
|
+
self.component_unique_id(self.Ids.Y_MIN_AUTO_GRAPH).to_string(),
|
|
335
|
+
"value",
|
|
336
|
+
),
|
|
337
|
+
Input(
|
|
338
|
+
self.component_unique_id(self.Ids.Y_MAX_AUTO_GRAPH).to_string(),
|
|
339
|
+
"value",
|
|
340
|
+
),
|
|
341
|
+
)
|
|
342
|
+
def set_y_min_max(
|
|
343
|
+
min_auto: List[str], max_auto: List[str]
|
|
344
|
+
) -> Tuple[bool, bool]:
|
|
345
|
+
return len(min_auto) == 1, len(max_auto) == 1
|
|
314
346
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
if
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
347
|
+
@callback(
|
|
348
|
+
Output(self.component_unique_id(self.Ids.PHASE).to_string(), "options"),
|
|
349
|
+
Output(self.component_unique_id(self.Ids.PHASE).to_string(), "value"),
|
|
350
|
+
Input(
|
|
351
|
+
self.component_unique_id(self.Ids.GRAPH_SOURCE).to_string(), "value"
|
|
352
|
+
),
|
|
353
|
+
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
354
|
+
State(self.component_unique_id(self.Ids.PHASE).to_string(), "value"),
|
|
355
|
+
)
|
|
356
|
+
def set_phases(
|
|
357
|
+
source: GraphSource,
|
|
358
|
+
ensemble: str,
|
|
359
|
+
current_value: str,
|
|
360
|
+
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
361
|
+
if ensemble is not None:
|
|
362
|
+
phases = self._menu_options[ensemble][source]["phases"]
|
|
363
|
+
options = [
|
|
364
|
+
{"label": phase.title(), "value": phase} for phase in phases
|
|
365
|
+
]
|
|
366
|
+
return options, no_update if current_value in phases else "total"
|
|
367
|
+
return [{"label": "Total", "value": "total"}], "total"
|
|
333
368
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
self.component_unique_id(self.Ids.
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
369
|
+
@callback(
|
|
370
|
+
Output(self.component_unique_id(self.Ids.ZONE).to_string(), "options"),
|
|
371
|
+
Output(self.component_unique_id(self.Ids.ZONE).to_string(), "value"),
|
|
372
|
+
Input(
|
|
373
|
+
self.component_unique_id(self.Ids.GRAPH_SOURCE).to_string(), "value"
|
|
374
|
+
),
|
|
375
|
+
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
376
|
+
State(self.component_unique_id(self.Ids.ZONE).to_string(), "value"),
|
|
377
|
+
)
|
|
378
|
+
def set_zones(
|
|
379
|
+
source: GraphSource,
|
|
380
|
+
ensemble: str,
|
|
381
|
+
current_value: str,
|
|
382
|
+
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
383
|
+
if ensemble is not None:
|
|
384
|
+
zones = self._menu_options[ensemble][source]["zones"]
|
|
385
|
+
if len(zones) > 0:
|
|
386
|
+
options = [
|
|
387
|
+
{"label": zone.title(), "value": zone} for zone in zones
|
|
388
|
+
]
|
|
389
|
+
return options, no_update if current_value in zones else "all"
|
|
390
|
+
return [{"label": "All", "value": "all"}], "all"
|
|
348
391
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
"
|
|
358
|
-
|
|
359
|
-
Input(self.component_unique_id(self.Ids.COLOR_BY).to_string(), "value"),
|
|
360
|
-
Input(self.component_unique_id(self.Ids.MARK_BY).to_string(), "value"),
|
|
361
|
-
)
|
|
362
|
-
def organize_color_and_mark_menus(
|
|
363
|
-
color_choice: str,
|
|
364
|
-
mark_choice: str,
|
|
365
|
-
) -> Tuple[List[Dict], str, Dict, Dict, Dict, Dict]:
|
|
366
|
-
mark_options = [
|
|
367
|
-
{"label": "Phase", "value": "phase"},
|
|
368
|
-
{"label": "None", "value": "none"},
|
|
369
|
-
]
|
|
370
|
-
if self._has_zones and color_choice == "containment":
|
|
371
|
-
mark_options.append({"label": "Zone", "value": "zone"})
|
|
372
|
-
if self._has_regions and color_choice == "containment":
|
|
373
|
-
mark_options.append({"label": "Region", "value": "region"})
|
|
374
|
-
if color_choice in ["zone", "region"]:
|
|
375
|
-
mark_options.append({"label": "Containment", "value": "containment"})
|
|
376
|
-
if mark_choice is None or mark_choice == color_choice:
|
|
377
|
-
mark_choice = "phase"
|
|
378
|
-
if mark_choice in ["zone", "region"] and color_choice in ["zone", "region"]:
|
|
379
|
-
mark_choice = "phase"
|
|
380
|
-
zone, region, phase, containment = _make_styles(
|
|
381
|
-
color_choice, mark_choice, self._has_zones, self._has_regions
|
|
392
|
+
@callback(
|
|
393
|
+
Output(
|
|
394
|
+
self.component_unique_id(self.Ids.REGION).to_string(), "options"
|
|
395
|
+
),
|
|
396
|
+
Output(self.component_unique_id(self.Ids.REGION).to_string(), "value"),
|
|
397
|
+
Input(
|
|
398
|
+
self.component_unique_id(self.Ids.GRAPH_SOURCE).to_string(), "value"
|
|
399
|
+
),
|
|
400
|
+
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
401
|
+
State(self.component_unique_id(self.Ids.REGION).to_string(), "value"),
|
|
382
402
|
)
|
|
383
|
-
|
|
403
|
+
def set_regions(
|
|
404
|
+
source: GraphSource,
|
|
405
|
+
ensemble: str,
|
|
406
|
+
current_value: str,
|
|
407
|
+
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
408
|
+
if ensemble is not None:
|
|
409
|
+
regions = self._menu_options[ensemble][source]["regions"]
|
|
410
|
+
if len(regions) > 0:
|
|
411
|
+
options = [
|
|
412
|
+
{"label": reg.title(), "value": reg} for reg in regions
|
|
413
|
+
]
|
|
414
|
+
return options, no_update if current_value in regions else "all"
|
|
415
|
+
return [{"label": "All", "value": "all"}], "all"
|
|
384
416
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
417
|
+
@callback(
|
|
418
|
+
Output(
|
|
419
|
+
self.component_unique_id(self.Ids.PLUME_GROUP).to_string(),
|
|
420
|
+
"options",
|
|
421
|
+
),
|
|
422
|
+
Output(
|
|
423
|
+
self.component_unique_id(self.Ids.PLUME_GROUP).to_string(), "value"
|
|
424
|
+
),
|
|
425
|
+
Input(
|
|
426
|
+
self.component_unique_id(self.Ids.GRAPH_SOURCE).to_string(), "value"
|
|
427
|
+
),
|
|
428
|
+
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
429
|
+
State(
|
|
430
|
+
self.component_unique_id(self.Ids.PLUME_GROUP).to_string(), "value"
|
|
431
|
+
),
|
|
432
|
+
)
|
|
433
|
+
def set_plume_groups(
|
|
434
|
+
source: GraphSource,
|
|
435
|
+
ensemble: str,
|
|
436
|
+
current_value: str,
|
|
437
|
+
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
438
|
+
if ensemble is not None:
|
|
439
|
+
plume_groups = self._menu_options[ensemble][source]["plume_groups"]
|
|
440
|
+
if len(plume_groups) > 0:
|
|
441
|
+
options = [
|
|
442
|
+
{"label": x.title(), "value": x} for x in plume_groups
|
|
443
|
+
]
|
|
444
|
+
return (
|
|
445
|
+
options,
|
|
446
|
+
no_update if current_value in plume_groups else "all",
|
|
447
|
+
)
|
|
448
|
+
return [{"label": "All", "value": "all"}], "all"
|
|
449
|
+
|
|
450
|
+
@callback(
|
|
451
|
+
Output(
|
|
452
|
+
self.component_unique_id(self.Ids.DATE_OPTION).to_string(),
|
|
453
|
+
"options",
|
|
454
|
+
),
|
|
455
|
+
Output(
|
|
456
|
+
self.component_unique_id(self.Ids.DATE_OPTION).to_string(), "value"
|
|
457
|
+
),
|
|
458
|
+
Input(
|
|
459
|
+
self.component_unique_id(self.Ids.GRAPH_SOURCE).to_string(), "value"
|
|
460
|
+
),
|
|
461
|
+
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
462
|
+
State(
|
|
463
|
+
self.component_unique_id(self.Ids.DATE_OPTION).to_string(), "value"
|
|
464
|
+
),
|
|
465
|
+
)
|
|
466
|
+
def set_date_option(
|
|
467
|
+
source: GraphSource,
|
|
468
|
+
ensemble: str,
|
|
469
|
+
current_value: str,
|
|
470
|
+
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
471
|
+
if ensemble is not None:
|
|
472
|
+
dates = self._menu_options[ensemble][source]["dates"]
|
|
473
|
+
options = [{"label": date.title(), "value": date} for date in dates]
|
|
474
|
+
return options, no_update if current_value in dates else dates[-1]
|
|
475
|
+
return [], None
|
|
476
|
+
|
|
477
|
+
# pylint: disable=too-many-branches
|
|
478
|
+
@callback(
|
|
479
|
+
Output(
|
|
480
|
+
self.component_unique_id(self.Ids.MARK_BY).to_string(), "options"
|
|
481
|
+
),
|
|
482
|
+
Output(self.component_unique_id(self.Ids.MARK_BY).to_string(), "value"),
|
|
483
|
+
Output(
|
|
484
|
+
self.component_unique_id(self.Ids.ZONE_COL).to_string(), "style"
|
|
485
|
+
),
|
|
486
|
+
Output(
|
|
487
|
+
self.component_unique_id(self.Ids.REGION_COL).to_string(), "style"
|
|
488
|
+
),
|
|
489
|
+
Output(
|
|
490
|
+
self.component_unique_id(self.Ids.PHASE_MENU).to_string(), "style"
|
|
491
|
+
),
|
|
492
|
+
Output(
|
|
493
|
+
self.component_unique_id(self.Ids.CONTAINMENT_MENU).to_string(),
|
|
494
|
+
"style",
|
|
495
|
+
),
|
|
496
|
+
Output(
|
|
497
|
+
self.component_unique_id(self.Ids.PLUME_GROUP_MENU).to_string(),
|
|
498
|
+
"style",
|
|
499
|
+
),
|
|
500
|
+
Input(self.component_unique_id(self.Ids.COLOR_BY).to_string(), "value"),
|
|
501
|
+
Input(self.component_unique_id(self.Ids.MARK_BY).to_string(), "value"),
|
|
502
|
+
)
|
|
503
|
+
def organize_color_and_mark_menus(
|
|
504
|
+
color_choice: str,
|
|
505
|
+
mark_choice: str,
|
|
506
|
+
) -> Tuple[List[Dict], str, Dict, Dict, Dict, Dict, Dict]:
|
|
507
|
+
mark_options = [
|
|
508
|
+
{"label": "None", "value": "none"},
|
|
509
|
+
]
|
|
510
|
+
if color_choice in ["containment", "phase"]:
|
|
511
|
+
if color_choice == "containment":
|
|
512
|
+
mark_options.append({"label": "Phase", "value": "phase"})
|
|
513
|
+
elif color_choice == "phase":
|
|
514
|
+
mark_options.append(
|
|
515
|
+
{"label": "Containment", "value": "containment"}
|
|
516
|
+
)
|
|
517
|
+
if self._content["zones"]:
|
|
518
|
+
mark_options.append({"label": "Zone", "value": "zone"})
|
|
519
|
+
if self._content["regions"]:
|
|
520
|
+
mark_options.append({"label": "Region", "value": "region"})
|
|
521
|
+
if self._content["plume_groups"]:
|
|
522
|
+
mark_options.append(
|
|
523
|
+
{"label": "Plume group", "value": "plume_group"}
|
|
524
|
+
)
|
|
525
|
+
elif color_choice in ["zone", "region", "plume_group"]:
|
|
526
|
+
mark_options += [
|
|
527
|
+
{"label": "Containment", "value": "containment"},
|
|
528
|
+
{"label": "Phase", "value": "phase"},
|
|
529
|
+
]
|
|
530
|
+
if (
|
|
531
|
+
color_choice in ["zone", "region"]
|
|
532
|
+
and self._content["plume_groups"]
|
|
533
|
+
):
|
|
534
|
+
mark_options.append(
|
|
535
|
+
{"label": "Plume group", "value": "plume_group"}
|
|
536
|
+
)
|
|
537
|
+
if color_choice == "plume_group":
|
|
538
|
+
if self._content["zones"]:
|
|
539
|
+
mark_options.append({"label": "Zone", "value": "zone"})
|
|
540
|
+
if self._content["regions"]:
|
|
541
|
+
mark_options.append({"label": "Region", "value": "region"})
|
|
542
|
+
if mark_choice is None or mark_choice == color_choice:
|
|
543
|
+
if color_choice != "phase":
|
|
544
|
+
mark_choice = "phase"
|
|
545
|
+
else:
|
|
546
|
+
mark_choice = "containment"
|
|
547
|
+
if mark_choice in ["zone", "region"] and color_choice in [
|
|
548
|
+
"zone",
|
|
549
|
+
"region",
|
|
550
|
+
]:
|
|
551
|
+
mark_choice = "phase"
|
|
552
|
+
zone, region, phase, containment, plume_group = _make_styles(
|
|
553
|
+
color_choice,
|
|
554
|
+
mark_choice,
|
|
555
|
+
self._content["zones"],
|
|
556
|
+
self._content["regions"],
|
|
557
|
+
self._content["plume_groups"],
|
|
558
|
+
)
|
|
559
|
+
return (
|
|
560
|
+
mark_options,
|
|
561
|
+
mark_choice,
|
|
562
|
+
zone,
|
|
563
|
+
region,
|
|
564
|
+
phase,
|
|
565
|
+
containment,
|
|
566
|
+
plume_group,
|
|
567
|
+
)
|
|
568
|
+
|
|
569
|
+
@callback(
|
|
570
|
+
Output(self.component_unique_id(self.Ids.ZONE).to_string(), "disabled"),
|
|
571
|
+
Output(
|
|
572
|
+
self.component_unique_id(self.Ids.REGION).to_string(), "disabled"
|
|
573
|
+
),
|
|
574
|
+
Input(self.component_unique_id(self.Ids.ZONE).to_string(), "value"),
|
|
575
|
+
Input(self.component_unique_id(self.Ids.REGION).to_string(), "value"),
|
|
576
|
+
)
|
|
577
|
+
def disable_zone_or_region(zone: str, region: str) -> Tuple[bool, bool]:
|
|
578
|
+
return region != "all", zone != "all"
|
|
393
579
|
|
|
394
580
|
|
|
395
581
|
class OpenDialogButton(html.Button):
|
|
@@ -484,6 +670,87 @@ class FilterSelectorLayout(wcc.Selectors):
|
|
|
484
670
|
)
|
|
485
671
|
|
|
486
672
|
|
|
673
|
+
class OpenVisualizationThresholdsButton(html.Button):
|
|
674
|
+
def __init__(self) -> None:
|
|
675
|
+
super().__init__(
|
|
676
|
+
LayoutLabels.VISUALIZATION_THRESHOLDS,
|
|
677
|
+
id=ViewSettings.Ids.VISUALIZATION_THRESHOLD_BUTTON,
|
|
678
|
+
style=LayoutStyle.THRESHOLDS_BUTTON,
|
|
679
|
+
n_clicks=0,
|
|
680
|
+
)
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
class VisualizationThresholdsLayout(wcc.Dialog):
|
|
684
|
+
"""Layout for the visualization thresholds dialog"""
|
|
685
|
+
|
|
686
|
+
def __init__(
|
|
687
|
+
self,
|
|
688
|
+
ids: List[str],
|
|
689
|
+
thresholds: MapThresholds,
|
|
690
|
+
visualization_update_id: str,
|
|
691
|
+
) -> None:
|
|
692
|
+
standard_thresholds = thresholds.standard_thresholds
|
|
693
|
+
|
|
694
|
+
fields = [
|
|
695
|
+
html.Div(
|
|
696
|
+
"Here you can select a filter for the visualization of the map, "
|
|
697
|
+
"hiding values smaller than the selected minimum cutoff. "
|
|
698
|
+
"After changing the threshold value, press 'Update' to have the map reappear. "
|
|
699
|
+
"A value of -1 can be used to visualize zeros."
|
|
700
|
+
),
|
|
701
|
+
html.Div("", style={"height": "30px"}),
|
|
702
|
+
html.Div(
|
|
703
|
+
[
|
|
704
|
+
html.Div("Property:", style={"width": "42%"}),
|
|
705
|
+
html.Div("Standard cutoff:", style={"width": "32%"}),
|
|
706
|
+
html.Div("Minimum cutoff:", style={"width": "25%"}),
|
|
707
|
+
],
|
|
708
|
+
style={"display": "flex", "flex-direction": "row"},
|
|
709
|
+
),
|
|
710
|
+
]
|
|
711
|
+
fields += [
|
|
712
|
+
html.Div(
|
|
713
|
+
[
|
|
714
|
+
html.Div(id, style={"width": "42%"}),
|
|
715
|
+
html.Div(standard_thresholds[id], style={"width": "32%"}),
|
|
716
|
+
dcc.Input(
|
|
717
|
+
id=id,
|
|
718
|
+
type="number",
|
|
719
|
+
value=standard_thresholds[id],
|
|
720
|
+
step="0.0005",
|
|
721
|
+
style={"width": "25%"},
|
|
722
|
+
),
|
|
723
|
+
],
|
|
724
|
+
style={"display": "flex", "flex-direction": "row"},
|
|
725
|
+
)
|
|
726
|
+
for id in ids
|
|
727
|
+
]
|
|
728
|
+
fields.append(html.Div(style={"height": "20px"}))
|
|
729
|
+
fields.append(
|
|
730
|
+
html.Div(
|
|
731
|
+
[
|
|
732
|
+
html.Div(style={"width": "80%"}),
|
|
733
|
+
html.Button(
|
|
734
|
+
"Update",
|
|
735
|
+
id=visualization_update_id,
|
|
736
|
+
style=LayoutStyle.VISUALIZATION_BUTTON,
|
|
737
|
+
n_clicks=0,
|
|
738
|
+
),
|
|
739
|
+
],
|
|
740
|
+
style={"display": "flex", "flex-direction": "row"},
|
|
741
|
+
)
|
|
742
|
+
)
|
|
743
|
+
super().__init__(
|
|
744
|
+
title=LayoutLabels.VISUALIZATION_THRESHOLDS,
|
|
745
|
+
id=ViewSettings.Ids.VISUALIZATION_THRESHOLD_DIALOG,
|
|
746
|
+
draggable=True,
|
|
747
|
+
open=False,
|
|
748
|
+
children=html.Div(
|
|
749
|
+
fields, style={"flex-direction": "column", "width": "500px"}
|
|
750
|
+
),
|
|
751
|
+
)
|
|
752
|
+
|
|
753
|
+
|
|
487
754
|
class MapSelectorLayout(wcc.Selectors):
|
|
488
755
|
_CM_RANGE = {
|
|
489
756
|
"display": "flex",
|
|
@@ -501,9 +768,9 @@ class MapSelectorLayout(wcc.Selectors):
|
|
|
501
768
|
cm_max_id: str,
|
|
502
769
|
cm_min_auto_id: str,
|
|
503
770
|
cm_max_auto_id: str,
|
|
504
|
-
visualization_threshold_id: str,
|
|
505
|
-
visualization_update_id: str,
|
|
506
771
|
mass_unit_id: str,
|
|
772
|
+
mass_unit_update_id: str,
|
|
773
|
+
map_attribute_names: FilteredMapAttribute,
|
|
507
774
|
):
|
|
508
775
|
default_colormap = (
|
|
509
776
|
"turbo (Seq)"
|
|
@@ -519,8 +786,8 @@ class MapSelectorLayout(wcc.Selectors):
|
|
|
519
786
|
"Property",
|
|
520
787
|
wcc.Dropdown(
|
|
521
788
|
id=property_id,
|
|
522
|
-
options=_compile_property_options(),
|
|
523
|
-
value=
|
|
789
|
+
options=_compile_property_options(map_attribute_names),
|
|
790
|
+
value=next(iter(map_attribute_names.filtered_values)).value,
|
|
524
791
|
clearable=False,
|
|
525
792
|
),
|
|
526
793
|
"Statistic",
|
|
@@ -568,32 +835,28 @@ class MapSelectorLayout(wcc.Selectors):
|
|
|
568
835
|
],
|
|
569
836
|
style=self._CM_RANGE,
|
|
570
837
|
),
|
|
571
|
-
"
|
|
838
|
+
"Mass unit (for mass maps)",
|
|
572
839
|
html.Div(
|
|
573
840
|
[
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
841
|
+
html.Div(
|
|
842
|
+
wcc.Dropdown(
|
|
843
|
+
id=mass_unit_id,
|
|
844
|
+
options=["kg", "tons", "M tons"],
|
|
845
|
+
value="tons",
|
|
846
|
+
clearable=False,
|
|
847
|
+
),
|
|
848
|
+
style={"width": "50%"},
|
|
579
849
|
),
|
|
580
|
-
html.Div(style={"width": "5%"}),
|
|
581
850
|
html.Button(
|
|
582
|
-
"Update",
|
|
583
|
-
id=
|
|
851
|
+
"Update unit",
|
|
852
|
+
id=mass_unit_update_id,
|
|
584
853
|
style=LayoutStyle.VISUALIZATION_BUTTON,
|
|
585
854
|
n_clicks=0,
|
|
586
855
|
),
|
|
587
856
|
],
|
|
588
857
|
style={"display": "flex"},
|
|
589
858
|
),
|
|
590
|
-
|
|
591
|
-
wcc.Dropdown(
|
|
592
|
-
id=mass_unit_id,
|
|
593
|
-
options=["kg", "tons", "M tons"],
|
|
594
|
-
value="kg",
|
|
595
|
-
clearable=False,
|
|
596
|
-
),
|
|
859
|
+
OpenVisualizationThresholdsButton(),
|
|
597
860
|
],
|
|
598
861
|
)
|
|
599
862
|
],
|
|
@@ -606,47 +869,65 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
606
869
|
"flexDirection": "row",
|
|
607
870
|
}
|
|
608
871
|
|
|
872
|
+
# pylint: disable=too-many-locals
|
|
609
873
|
def __init__(
|
|
610
874
|
self,
|
|
611
875
|
graph_source_id: str,
|
|
612
876
|
co2_scale_id: str,
|
|
613
877
|
y_min_ids: List[str],
|
|
614
878
|
y_max_ids: List[str],
|
|
615
|
-
containment_ids:
|
|
616
|
-
|
|
617
|
-
has_regions: bool,
|
|
879
|
+
containment_ids: Dict[str, str], # ViewSettings.Ids
|
|
880
|
+
content: Dict[str, bool],
|
|
618
881
|
):
|
|
619
|
-
disp_zone = "flex" if
|
|
620
|
-
disp_region = "flex" if
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
882
|
+
disp_zone = "flex" if content["zones"] else "none"
|
|
883
|
+
disp_region = "flex" if content["regions"] else "none"
|
|
884
|
+
disp_plume_group = "flex" if content["plume_groups"] else "none"
|
|
885
|
+
color_options = [
|
|
886
|
+
{"label": "Containment", "value": "containment"},
|
|
887
|
+
{"label": "Phase", "value": "phase"},
|
|
888
|
+
]
|
|
889
|
+
mark_options = [
|
|
890
|
+
{"label": "Phase", "value": "phase"},
|
|
891
|
+
{"label": "Containment", "value": "containment"},
|
|
892
|
+
]
|
|
893
|
+
if content["zones"]:
|
|
629
894
|
color_options.append({"label": "Zone", "value": "zone"})
|
|
630
895
|
mark_options.append({"label": "Zone", "value": "zone"})
|
|
631
|
-
if
|
|
896
|
+
if content["regions"]:
|
|
632
897
|
color_options.append({"label": "Region", "value": "region"})
|
|
633
898
|
mark_options.append({"label": "Region", "value": "region"})
|
|
899
|
+
if content["plume_groups"]:
|
|
900
|
+
color_options.append({"label": "Plume group", "value": "plume_group"})
|
|
901
|
+
mark_options.append({"label": "Plume group", "value": "plume_group"})
|
|
902
|
+
source_options = []
|
|
903
|
+
if content["mass"]:
|
|
904
|
+
source_options.append(GraphSource.CONTAINMENT_MASS)
|
|
905
|
+
if content["volume"]:
|
|
906
|
+
source_options.append(GraphSource.CONTAINMENT_ACTUAL_VOLUME)
|
|
907
|
+
if content["unsmry"]:
|
|
908
|
+
source_options.append(GraphSource.UNSMRY)
|
|
909
|
+
unit_options, init_unit = (
|
|
910
|
+
(list(Co2VolumeScale), Co2VolumeScale.BILLION_CUBIC_METERS)
|
|
911
|
+
if source_options[0] == GraphSource.CONTAINMENT_ACTUAL_VOLUME
|
|
912
|
+
else (list(Co2MassScale), Co2MassScale.MTONS)
|
|
913
|
+
)
|
|
914
|
+
ids = ViewSettings.Ids
|
|
634
915
|
super().__init__(
|
|
635
916
|
label="Graph Settings",
|
|
636
|
-
open_details=
|
|
917
|
+
open_details=not content["maps"],
|
|
637
918
|
children=[
|
|
638
919
|
"Source",
|
|
639
920
|
wcc.Dropdown(
|
|
640
921
|
id=graph_source_id,
|
|
641
|
-
options=
|
|
642
|
-
value=
|
|
922
|
+
options=source_options,
|
|
923
|
+
value=source_options[0],
|
|
643
924
|
clearable=False,
|
|
644
925
|
),
|
|
645
926
|
"Unit",
|
|
646
927
|
wcc.Dropdown(
|
|
647
928
|
id=co2_scale_id,
|
|
648
|
-
options=
|
|
649
|
-
value=
|
|
929
|
+
options=unit_options,
|
|
930
|
+
value=init_unit,
|
|
650
931
|
clearable=False,
|
|
651
932
|
),
|
|
652
933
|
html.Div(
|
|
@@ -657,7 +938,7 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
657
938
|
wcc.Dropdown(
|
|
658
939
|
options=color_options,
|
|
659
940
|
value="containment",
|
|
660
|
-
id=containment_ids[
|
|
941
|
+
id=containment_ids[ids.COLOR_BY],
|
|
661
942
|
clearable=False,
|
|
662
943
|
),
|
|
663
944
|
],
|
|
@@ -672,7 +953,7 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
672
953
|
wcc.Dropdown(
|
|
673
954
|
options=mark_options,
|
|
674
955
|
value="phase",
|
|
675
|
-
id=containment_ids[
|
|
956
|
+
id=containment_ids[ids.MARK_BY],
|
|
676
957
|
clearable=False,
|
|
677
958
|
),
|
|
678
959
|
],
|
|
@@ -683,7 +964,7 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
683
964
|
),
|
|
684
965
|
],
|
|
685
966
|
style={
|
|
686
|
-
"display": "flex",
|
|
967
|
+
"display": "flex",
|
|
687
968
|
"flex-direction": "row",
|
|
688
969
|
"margin-top": "10px",
|
|
689
970
|
"margin-bottom": "1px",
|
|
@@ -695,7 +976,7 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
695
976
|
dcc.RadioItems(
|
|
696
977
|
options=["color", "marking"],
|
|
697
978
|
value="color",
|
|
698
|
-
id=containment_ids[
|
|
979
|
+
id=containment_ids[ids.SORT_PLOT],
|
|
699
980
|
inline=True,
|
|
700
981
|
),
|
|
701
982
|
],
|
|
@@ -712,14 +993,26 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
712
993
|
[
|
|
713
994
|
"Zone",
|
|
714
995
|
wcc.Dropdown(
|
|
996
|
+
options=[{"label": "All", "value": "all"}],
|
|
715
997
|
value="all",
|
|
716
|
-
id=containment_ids[
|
|
998
|
+
id=containment_ids[ids.ZONE],
|
|
717
999
|
clearable=False,
|
|
718
1000
|
),
|
|
719
1001
|
],
|
|
720
|
-
id=containment_ids[
|
|
1002
|
+
id=containment_ids[ids.ZONE_COL],
|
|
721
1003
|
style={
|
|
722
|
-
"width":
|
|
1004
|
+
"width": (
|
|
1005
|
+
"33%"
|
|
1006
|
+
if (content["regions"] and content["plume_groups"])
|
|
1007
|
+
else (
|
|
1008
|
+
"50%"
|
|
1009
|
+
if (
|
|
1010
|
+
content["regions"]
|
|
1011
|
+
or content["plume_groups"]
|
|
1012
|
+
)
|
|
1013
|
+
else "100%"
|
|
1014
|
+
)
|
|
1015
|
+
),
|
|
723
1016
|
"display": disp_zone,
|
|
724
1017
|
"flex-direction": "column",
|
|
725
1018
|
},
|
|
@@ -728,14 +1021,23 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
728
1021
|
[
|
|
729
1022
|
"Region",
|
|
730
1023
|
wcc.Dropdown(
|
|
1024
|
+
options=[{"label": "All", "value": "all"}],
|
|
731
1025
|
value="all",
|
|
732
|
-
id=containment_ids[
|
|
1026
|
+
id=containment_ids[ids.REGION],
|
|
733
1027
|
clearable=False,
|
|
734
1028
|
),
|
|
735
1029
|
],
|
|
736
|
-
id=containment_ids[
|
|
1030
|
+
id=containment_ids[ids.REGION_COL],
|
|
737
1031
|
style={
|
|
738
|
-
"width":
|
|
1032
|
+
"width": (
|
|
1033
|
+
"33%"
|
|
1034
|
+
if (content["zones"] and content["plume_groups"])
|
|
1035
|
+
else (
|
|
1036
|
+
"50%"
|
|
1037
|
+
if (content["zones"] or content["plume_groups"])
|
|
1038
|
+
else "100%"
|
|
1039
|
+
)
|
|
1040
|
+
),
|
|
739
1041
|
"display": disp_region,
|
|
740
1042
|
"flex-direction": "column",
|
|
741
1043
|
},
|
|
@@ -744,12 +1046,13 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
744
1046
|
[
|
|
745
1047
|
"Phase",
|
|
746
1048
|
wcc.Dropdown(
|
|
1049
|
+
options=[{"label": "Total", "value": "total"}],
|
|
747
1050
|
value="total",
|
|
748
1051
|
clearable=False,
|
|
749
|
-
id=containment_ids[
|
|
1052
|
+
id=containment_ids[ids.PHASE],
|
|
750
1053
|
),
|
|
751
1054
|
],
|
|
752
|
-
id=containment_ids[
|
|
1055
|
+
id=containment_ids[ids.PHASE_MENU],
|
|
753
1056
|
style={"display": "none"},
|
|
754
1057
|
),
|
|
755
1058
|
html.Div(
|
|
@@ -757,50 +1060,161 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
757
1060
|
"Containment",
|
|
758
1061
|
wcc.Dropdown(
|
|
759
1062
|
options=[
|
|
760
|
-
{"label": "
|
|
1063
|
+
{"label": "All areas", "value": "total"},
|
|
761
1064
|
{"label": "Contained", "value": "contained"},
|
|
762
1065
|
{"label": "Outside", "value": "outside"},
|
|
763
1066
|
{"label": "Hazardous", "value": "hazardous"},
|
|
764
1067
|
],
|
|
765
1068
|
value="total",
|
|
766
1069
|
clearable=False,
|
|
767
|
-
id=containment_ids[
|
|
1070
|
+
id=containment_ids[ids.CONTAINMENT],
|
|
768
1071
|
),
|
|
769
1072
|
],
|
|
770
|
-
id=containment_ids[
|
|
1073
|
+
id=containment_ids[ids.CONTAINMENT_MENU],
|
|
771
1074
|
style={"display": "none"},
|
|
772
1075
|
),
|
|
1076
|
+
html.Div(
|
|
1077
|
+
[
|
|
1078
|
+
"Plume",
|
|
1079
|
+
wcc.Dropdown(
|
|
1080
|
+
options=[{"label": "All", "value": "all"}],
|
|
1081
|
+
value="all",
|
|
1082
|
+
id=containment_ids[ids.PLUME_GROUP],
|
|
1083
|
+
clearable=False,
|
|
1084
|
+
),
|
|
1085
|
+
],
|
|
1086
|
+
id=containment_ids[ids.PLUME_GROUP_MENU],
|
|
1087
|
+
style={
|
|
1088
|
+
"width": (
|
|
1089
|
+
"33%"
|
|
1090
|
+
if (content["zones"] and content["regions"])
|
|
1091
|
+
else (
|
|
1092
|
+
"50%"
|
|
1093
|
+
if (content["zones"] or content["regions"])
|
|
1094
|
+
else "100%"
|
|
1095
|
+
)
|
|
1096
|
+
),
|
|
1097
|
+
"display": disp_plume_group,
|
|
1098
|
+
"flex-direction": "column",
|
|
1099
|
+
},
|
|
1100
|
+
),
|
|
773
1101
|
],
|
|
774
|
-
id=containment_ids[
|
|
1102
|
+
id=containment_ids[ids.ZONE_REGION],
|
|
775
1103
|
style={"display": "flex"},
|
|
776
1104
|
),
|
|
777
1105
|
html.Div(
|
|
778
|
-
"
|
|
1106
|
+
"Time plot options:",
|
|
779
1107
|
style={"margin-top": "10px"},
|
|
780
1108
|
),
|
|
781
|
-
"Minimum",
|
|
782
1109
|
html.Div(
|
|
783
1110
|
[
|
|
784
|
-
dcc.
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1111
|
+
dcc.RadioItems(
|
|
1112
|
+
options=[
|
|
1113
|
+
{"label": "Realizations", "value": "real"},
|
|
1114
|
+
{"label": "Mean/P10/P90", "value": "stat"},
|
|
1115
|
+
],
|
|
1116
|
+
value="real",
|
|
1117
|
+
id=containment_ids[ids.REAL_OR_STAT],
|
|
1118
|
+
inline=True,
|
|
1119
|
+
),
|
|
1120
|
+
],
|
|
1121
|
+
style={
|
|
1122
|
+
"display": "flex",
|
|
1123
|
+
"flex-direction": "row",
|
|
1124
|
+
},
|
|
1125
|
+
),
|
|
1126
|
+
html.Div(
|
|
1127
|
+
"State at date:",
|
|
1128
|
+
style={"margin-top": "8"},
|
|
1129
|
+
),
|
|
1130
|
+
html.Div(
|
|
1131
|
+
[
|
|
1132
|
+
wcc.Dropdown(
|
|
1133
|
+
id=containment_ids[ids.DATE_OPTION],
|
|
1134
|
+
clearable=False,
|
|
789
1135
|
),
|
|
790
1136
|
],
|
|
791
|
-
|
|
1137
|
+
id=containment_ids[ids.DATE_OPTION_COL],
|
|
1138
|
+
style={
|
|
1139
|
+
"width": "100%",
|
|
1140
|
+
"flex-direction": "row",
|
|
1141
|
+
},
|
|
792
1142
|
),
|
|
793
|
-
"Maximum",
|
|
794
1143
|
html.Div(
|
|
795
1144
|
[
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
[
|
|
799
|
-
|
|
800
|
-
|
|
1145
|
+
"Fix minimum y-value",
|
|
1146
|
+
html.Div(
|
|
1147
|
+
[
|
|
1148
|
+
dcc.Input(id=y_min_ids[0], type="number"),
|
|
1149
|
+
dcc.Checklist(
|
|
1150
|
+
["Auto"],
|
|
1151
|
+
["Auto"],
|
|
1152
|
+
id=y_min_ids[1],
|
|
1153
|
+
),
|
|
1154
|
+
],
|
|
1155
|
+
style=self._CM_RANGE,
|
|
1156
|
+
),
|
|
1157
|
+
"Fix maximum y-value",
|
|
1158
|
+
html.Div(
|
|
1159
|
+
[
|
|
1160
|
+
dcc.Input(id=y_max_ids[0], type="number"),
|
|
1161
|
+
dcc.Checklist(
|
|
1162
|
+
["Auto"],
|
|
1163
|
+
["Auto"],
|
|
1164
|
+
id=y_max_ids[1],
|
|
1165
|
+
),
|
|
1166
|
+
],
|
|
1167
|
+
style=self._CM_RANGE,
|
|
801
1168
|
),
|
|
802
1169
|
],
|
|
803
|
-
style=
|
|
1170
|
+
style={
|
|
1171
|
+
"display": "flex",
|
|
1172
|
+
"flex-direction": "column",
|
|
1173
|
+
},
|
|
1174
|
+
id=containment_ids[ids.Y_LIM_OPTIONS],
|
|
1175
|
+
),
|
|
1176
|
+
html.Div(
|
|
1177
|
+
"Statistics tab:",
|
|
1178
|
+
style={"margin-top": "10px"},
|
|
1179
|
+
),
|
|
1180
|
+
html.Div(
|
|
1181
|
+
[
|
|
1182
|
+
dcc.RadioItems(
|
|
1183
|
+
options=[
|
|
1184
|
+
{
|
|
1185
|
+
"label": "Probability plot",
|
|
1186
|
+
"value": StatisticsTabOption.PROBABILITY_PLOT,
|
|
1187
|
+
},
|
|
1188
|
+
{
|
|
1189
|
+
"label": "Box plot",
|
|
1190
|
+
"value": StatisticsTabOption.BOX_PLOT,
|
|
1191
|
+
},
|
|
1192
|
+
],
|
|
1193
|
+
value=StatisticsTabOption.PROBABILITY_PLOT,
|
|
1194
|
+
id=containment_ids[ids.STATISTICS_TAB_OPTION],
|
|
1195
|
+
),
|
|
1196
|
+
],
|
|
1197
|
+
),
|
|
1198
|
+
html.Div(
|
|
1199
|
+
"Box plot points to show:",
|
|
1200
|
+
style={"margin-top": "10px"},
|
|
1201
|
+
),
|
|
1202
|
+
html.Div(
|
|
1203
|
+
[
|
|
1204
|
+
dcc.RadioItems(
|
|
1205
|
+
options=[
|
|
1206
|
+
{"label": "All", "value": "all_points"},
|
|
1207
|
+
{"label": "Outliers", "value": "only_outliers"},
|
|
1208
|
+
],
|
|
1209
|
+
value="only_outliers",
|
|
1210
|
+
id=containment_ids[ids.BOX_SHOW_POINTS],
|
|
1211
|
+
inline=True,
|
|
1212
|
+
),
|
|
1213
|
+
],
|
|
1214
|
+
style={
|
|
1215
|
+
"display": "flex",
|
|
1216
|
+
"flex-direction": "row",
|
|
1217
|
+
},
|
|
804
1218
|
),
|
|
805
1219
|
],
|
|
806
1220
|
)
|
|
@@ -848,7 +1262,13 @@ class ExperimentalFeaturesLayout(wcc.Selectors):
|
|
|
848
1262
|
|
|
849
1263
|
|
|
850
1264
|
class EnsembleSelectorLayout(wcc.Selectors):
|
|
851
|
-
def __init__(
|
|
1265
|
+
def __init__(
|
|
1266
|
+
self,
|
|
1267
|
+
ensemble_id: str,
|
|
1268
|
+
realization_id: str,
|
|
1269
|
+
all_real_id: str,
|
|
1270
|
+
ensembles: List[str],
|
|
1271
|
+
):
|
|
852
1272
|
super().__init__(
|
|
853
1273
|
label="Ensemble",
|
|
854
1274
|
open_details=True,
|
|
@@ -860,7 +1280,23 @@ class EnsembleSelectorLayout(wcc.Selectors):
|
|
|
860
1280
|
value=ensembles[0],
|
|
861
1281
|
clearable=False,
|
|
862
1282
|
),
|
|
863
|
-
|
|
1283
|
+
html.Div(
|
|
1284
|
+
[
|
|
1285
|
+
html.Div("Realization", style={"width": "50%"}),
|
|
1286
|
+
html.Button(
|
|
1287
|
+
"Select all",
|
|
1288
|
+
id=all_real_id,
|
|
1289
|
+
style=LayoutStyle.ALL_REAL_BUTTON,
|
|
1290
|
+
n_clicks=0,
|
|
1291
|
+
),
|
|
1292
|
+
],
|
|
1293
|
+
style={
|
|
1294
|
+
"display": "flex",
|
|
1295
|
+
"flex-direction": "row",
|
|
1296
|
+
"margin-top": "3px",
|
|
1297
|
+
"margin-bottom": "3px",
|
|
1298
|
+
},
|
|
1299
|
+
),
|
|
864
1300
|
wcc.SelectWithLabel(
|
|
865
1301
|
id=realization_id,
|
|
866
1302
|
value=[],
|
|
@@ -870,44 +1306,34 @@ class EnsembleSelectorLayout(wcc.Selectors):
|
|
|
870
1306
|
)
|
|
871
1307
|
|
|
872
1308
|
|
|
873
|
-
def
|
|
1309
|
+
def _create_left_side_menu(
|
|
1310
|
+
map_group: str, map_attribute_names: FilteredMapAttribute
|
|
1311
|
+
) -> List:
|
|
1312
|
+
title = {
|
|
1313
|
+
"label": html.Span([f"{map_group}:"], style={"text-decoration": "underline"}),
|
|
1314
|
+
"value": "",
|
|
1315
|
+
"disabled": True,
|
|
1316
|
+
}
|
|
1317
|
+
map_attribute_list = [
|
|
1318
|
+
{"label": MapAttribute[key.name].value, "value": MapAttribute[key.name].value}
|
|
1319
|
+
for key in map_attribute_names.filtered_values.keys()
|
|
1320
|
+
if map_group_labels[MapGroup[key.name].value] == map_group
|
|
1321
|
+
]
|
|
1322
|
+
return [title] + map_attribute_list
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
def _compile_property_options(
|
|
1326
|
+
map_attribute_names: FilteredMapAttribute,
|
|
1327
|
+
) -> List[Dict[str, Any]]:
|
|
1328
|
+
requested_map_groups = [
|
|
1329
|
+
map_group_labels[MapGroup[key.name].value]
|
|
1330
|
+
for key in map_attribute_names.filtered_values.keys()
|
|
1331
|
+
]
|
|
1332
|
+
unique_requested_map_groups = list(set(requested_map_groups))
|
|
874
1333
|
return [
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
"disabled": True,
|
|
879
|
-
},
|
|
880
|
-
{
|
|
881
|
-
"label": MapAttribute.MIGRATION_TIME_SGAS.value,
|
|
882
|
-
"value": MapAttribute.MIGRATION_TIME_SGAS.value,
|
|
883
|
-
},
|
|
884
|
-
{"label": MapAttribute.MAX_SGAS.value, "value": MapAttribute.MAX_SGAS.value},
|
|
885
|
-
{
|
|
886
|
-
"label": MapAttribute.SGAS_PLUME.value,
|
|
887
|
-
"value": MapAttribute.SGAS_PLUME.value,
|
|
888
|
-
},
|
|
889
|
-
{
|
|
890
|
-
"label": html.Span(["AMFG:"], style={"text-decoration": "underline"}),
|
|
891
|
-
"value": "",
|
|
892
|
-
"disabled": True,
|
|
893
|
-
},
|
|
894
|
-
{
|
|
895
|
-
"label": MapAttribute.MIGRATION_TIME_AMFG.value,
|
|
896
|
-
"value": MapAttribute.MIGRATION_TIME_AMFG.value,
|
|
897
|
-
},
|
|
898
|
-
{"label": MapAttribute.MAX_AMFG.value, "value": MapAttribute.MAX_AMFG.value},
|
|
899
|
-
{
|
|
900
|
-
"label": MapAttribute.AMFG_PLUME.value,
|
|
901
|
-
"value": MapAttribute.AMFG_PLUME.value,
|
|
902
|
-
},
|
|
903
|
-
{
|
|
904
|
-
"label": html.Span(["MASS:"], style={"text-decoration": "underline"}),
|
|
905
|
-
"value": "",
|
|
906
|
-
"disabled": True,
|
|
907
|
-
},
|
|
908
|
-
{"label": MapAttribute.MASS.value, "value": MapAttribute.MASS.value},
|
|
909
|
-
{"label": MapAttribute.DISSOLVED.value, "value": MapAttribute.DISSOLVED.value},
|
|
910
|
-
{"label": MapAttribute.FREE.value, "value": MapAttribute.FREE.value},
|
|
1334
|
+
element
|
|
1335
|
+
for group in unique_requested_map_groups
|
|
1336
|
+
for element in _create_left_side_menu(group, map_attribute_names)
|
|
911
1337
|
]
|
|
912
1338
|
|
|
913
1339
|
|
|
@@ -962,7 +1388,7 @@ def get_emails() -> str:
|
|
|
962
1388
|
for i, m in enumerate(
|
|
963
1389
|
[
|
|
964
1390
|
"GLLNAdpthons/bnl",
|
|
965
|
-
"
|
|
1391
|
+
"`ijBgswklmp,amo",
|
|
966
1392
|
"pfhCmq-ml",
|
|
967
1393
|
"bjarnajDjv*jk",
|
|
968
1394
|
"vlfdfmdEkw+kj",
|
|
@@ -972,45 +1398,204 @@ def get_emails() -> str:
|
|
|
972
1398
|
return ";".join(emails[:2]) + "?cc=" + ";".join(emails[2:])
|
|
973
1399
|
|
|
974
1400
|
|
|
1401
|
+
# pylint: disable=too-many-statements, too-many-branches
|
|
975
1402
|
def _make_styles(
|
|
976
1403
|
color_choice: str,
|
|
977
1404
|
mark_choice: str,
|
|
978
1405
|
has_zones: bool,
|
|
979
1406
|
has_regions: bool,
|
|
1407
|
+
has_plume_groups: bool,
|
|
980
1408
|
) -> List[Dict[str, str]]:
|
|
981
1409
|
zone = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
982
1410
|
region = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
983
1411
|
phase = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
984
1412
|
containment = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
1413
|
+
plume_group = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
985
1414
|
if color_choice == "containment":
|
|
986
1415
|
if mark_choice == "phase":
|
|
987
|
-
zone["width"] = "50%" if has_regions else "100%"
|
|
988
1416
|
zone["display"] = "flex" if has_zones else "none"
|
|
989
|
-
region["width"] = "50%" if has_zones else "100%"
|
|
990
1417
|
region["display"] = "flex" if has_regions else "none"
|
|
1418
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1419
|
+
n_categories = has_regions + has_zones + has_plume_groups
|
|
1420
|
+
if n_categories == 3:
|
|
1421
|
+
zone["width"] = region["width"] = plume_group["width"] = "33%"
|
|
1422
|
+
elif n_categories == 2:
|
|
1423
|
+
zone["width"] = region["width"] = plume_group["width"] = "50%"
|
|
1424
|
+
else:
|
|
1425
|
+
zone["width"] = region["width"] = plume_group["width"] = "100%"
|
|
1426
|
+
elif mark_choice == "plume_group":
|
|
1427
|
+
zone["display"] = "flex" if has_zones else "none"
|
|
1428
|
+
region["display"] = "flex" if has_regions else "none"
|
|
1429
|
+
phase["display"] = "flex"
|
|
1430
|
+
n_categories = 1 + has_regions + has_zones
|
|
1431
|
+
if n_categories == 3:
|
|
1432
|
+
zone["width"] = region["width"] = phase["width"] = "33%"
|
|
1433
|
+
elif n_categories == 2:
|
|
1434
|
+
zone["width"] = region["width"] = phase["width"] = "50%"
|
|
1435
|
+
else:
|
|
1436
|
+
zone["width"] = region["width"] = phase["width"] = "100%"
|
|
991
1437
|
elif mark_choice == "none":
|
|
992
|
-
zone["width"] = "33%" if has_regions else "50%"
|
|
993
1438
|
zone["display"] = "flex" if has_zones else "none"
|
|
994
|
-
region["width"] = "33%" if has_zones else "50%"
|
|
995
1439
|
region["display"] = "flex" if has_regions else "none"
|
|
996
|
-
|
|
997
|
-
"33%"
|
|
998
|
-
if has_zones and has_regions
|
|
999
|
-
else "100%"
|
|
1000
|
-
if not has_regions and not has_zones
|
|
1001
|
-
else "50%"
|
|
1002
|
-
)
|
|
1440
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1003
1441
|
phase["display"] = "flex"
|
|
1442
|
+
n_categories = 1 + has_regions + has_zones + has_plume_groups
|
|
1443
|
+
if n_categories == 4:
|
|
1444
|
+
phase["width"] = zone["width"] = region["width"] = plume_group[
|
|
1445
|
+
"width"
|
|
1446
|
+
] = "25%"
|
|
1447
|
+
elif n_categories == 3:
|
|
1448
|
+
phase["width"] = zone["width"] = region["width"] = plume_group[
|
|
1449
|
+
"width"
|
|
1450
|
+
] = "33%"
|
|
1451
|
+
elif n_categories == 2:
|
|
1452
|
+
phase["width"] = zone["width"] = region["width"] = plume_group[
|
|
1453
|
+
"width"
|
|
1454
|
+
] = "50%"
|
|
1455
|
+
else:
|
|
1456
|
+
phase["width"] = zone["width"] = region["width"] = plume_group[
|
|
1457
|
+
"width"
|
|
1458
|
+
] = "100%"
|
|
1459
|
+
else: # mark_choice == "zone" / "region"
|
|
1460
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1461
|
+
n_categories = 1 + has_plume_groups
|
|
1462
|
+
if n_categories == 2:
|
|
1463
|
+
phase["width"] = plume_group["width"] = "50%"
|
|
1464
|
+
else:
|
|
1465
|
+
phase["width"] = plume_group["width"] = "100%"
|
|
1466
|
+
phase["display"] = "flex"
|
|
1467
|
+
elif color_choice == "phase":
|
|
1468
|
+
if mark_choice == "containment":
|
|
1469
|
+
zone["display"] = "flex" if has_zones else "none"
|
|
1470
|
+
region["display"] = "flex" if has_regions else "none"
|
|
1471
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1472
|
+
n_categories = has_regions + has_zones + has_plume_groups
|
|
1473
|
+
if n_categories == 3:
|
|
1474
|
+
zone["width"] = region["width"] = plume_group["width"] = "33%"
|
|
1475
|
+
elif n_categories == 2:
|
|
1476
|
+
zone["width"] = region["width"] = plume_group["width"] = "50%"
|
|
1477
|
+
else:
|
|
1478
|
+
zone["width"] = region["width"] = plume_group["width"] = "100%"
|
|
1479
|
+
elif mark_choice == "plume_group":
|
|
1480
|
+
zone["display"] = "flex" if has_zones else "none"
|
|
1481
|
+
region["display"] = "flex" if has_regions else "none"
|
|
1482
|
+
containment["display"] = "flex"
|
|
1483
|
+
n_categories = 1 + has_regions + has_zones
|
|
1484
|
+
if n_categories == 3:
|
|
1485
|
+
zone["width"] = region["width"] = containment["width"] = "33%"
|
|
1486
|
+
elif n_categories == 2:
|
|
1487
|
+
zone["width"] = region["width"] = containment["width"] = "50%"
|
|
1488
|
+
else:
|
|
1489
|
+
zone["width"] = region["width"] = containment["width"] = "100%"
|
|
1490
|
+
elif mark_choice == "none":
|
|
1491
|
+
zone["display"] = "flex" if has_zones else "none"
|
|
1492
|
+
region["display"] = "flex" if has_regions else "none"
|
|
1493
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1494
|
+
containment["display"] = "flex"
|
|
1495
|
+
n_categories = 1 + has_regions + has_zones + has_plume_groups
|
|
1496
|
+
if n_categories == 4:
|
|
1497
|
+
containment["width"] = zone["width"] = region["width"] = plume_group[
|
|
1498
|
+
"width"
|
|
1499
|
+
] = "25%"
|
|
1500
|
+
elif n_categories == 3:
|
|
1501
|
+
containment["width"] = zone["width"] = region["width"] = plume_group[
|
|
1502
|
+
"width"
|
|
1503
|
+
] = "33%"
|
|
1504
|
+
elif n_categories == 2:
|
|
1505
|
+
containment["width"] = zone["width"] = region["width"] = plume_group[
|
|
1506
|
+
"width"
|
|
1507
|
+
] = "50%"
|
|
1508
|
+
else:
|
|
1509
|
+
containment["width"] = zone["width"] = region["width"] = plume_group[
|
|
1510
|
+
"width"
|
|
1511
|
+
] = "100%"
|
|
1004
1512
|
else: # mark_choice == "zone" / "region"
|
|
1513
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1514
|
+
n_categories = 1 + has_plume_groups
|
|
1515
|
+
if n_categories == 2:
|
|
1516
|
+
containment["width"] = plume_group["width"] = "50%"
|
|
1517
|
+
else:
|
|
1518
|
+
containment["width"] = plume_group["width"] = "100%"
|
|
1519
|
+
containment["display"] = "flex"
|
|
1520
|
+
elif color_choice == "plume_group":
|
|
1521
|
+
if mark_choice == "phase":
|
|
1522
|
+
zone["display"] = "flex" if has_zones else "none"
|
|
1523
|
+
region["display"] = "flex" if has_regions else "none"
|
|
1524
|
+
containment["display"] = "flex"
|
|
1525
|
+
n_categories = 1 + has_zones + has_regions
|
|
1526
|
+
if n_categories == 3:
|
|
1527
|
+
zone["width"] = region["width"] = containment["width"] = "33%"
|
|
1528
|
+
elif n_categories == 2:
|
|
1529
|
+
zone["width"] = region["width"] = containment["width"] = "50%"
|
|
1530
|
+
else:
|
|
1531
|
+
zone["width"] = region["width"] = containment["width"] = "100%"
|
|
1532
|
+
elif mark_choice == "containment":
|
|
1533
|
+
zone["display"] = "flex" if has_zones else "none"
|
|
1534
|
+
region["display"] = "flex" if has_regions else "none"
|
|
1005
1535
|
phase["display"] = "flex"
|
|
1536
|
+
n_categories = 1 + has_zones + has_regions
|
|
1537
|
+
if n_categories == 3:
|
|
1538
|
+
zone["width"] = region["width"] = phase["width"] = "33%"
|
|
1539
|
+
elif n_categories == 2:
|
|
1540
|
+
zone["width"] = region["width"] = phase["width"] = "50%"
|
|
1541
|
+
else:
|
|
1542
|
+
zone["width"] = region["width"] = phase["width"] = "100%"
|
|
1543
|
+
elif mark_choice == "none":
|
|
1544
|
+
zone["display"] = "flex" if has_zones else "none"
|
|
1545
|
+
region["display"] = "flex" if has_regions else "none"
|
|
1546
|
+
phase["display"] = "flex"
|
|
1547
|
+
containment["display"] = "flex"
|
|
1548
|
+
n_categories = 2 + has_zones + has_regions
|
|
1549
|
+
if n_categories == 4:
|
|
1550
|
+
zone["width"] = region["width"] = phase["width"] = containment[
|
|
1551
|
+
"width"
|
|
1552
|
+
] = "25%"
|
|
1553
|
+
elif n_categories == 3:
|
|
1554
|
+
zone["width"] = region["width"] = phase["width"] = containment[
|
|
1555
|
+
"width"
|
|
1556
|
+
] = "33%"
|
|
1557
|
+
elif n_categories == 2:
|
|
1558
|
+
zone["width"] = region["width"] = phase["width"] = containment[
|
|
1559
|
+
"width"
|
|
1560
|
+
] = "50%"
|
|
1561
|
+
else:
|
|
1562
|
+
zone["width"] = region["width"] = phase["width"] = containment[
|
|
1563
|
+
"width"
|
|
1564
|
+
] = "100%"
|
|
1565
|
+
else: # mark == "zone/region"
|
|
1566
|
+
phase["display"] = "flex"
|
|
1567
|
+
containment["display"] = "flex"
|
|
1568
|
+
phase["width"] = containment["width"] = "50%"
|
|
1006
1569
|
else: # color_choice == "zone" / "region"
|
|
1007
1570
|
if mark_choice == "phase":
|
|
1571
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1008
1572
|
containment["display"] = "flex"
|
|
1573
|
+
n_categories = 1 + has_plume_groups
|
|
1574
|
+
if n_categories == 2:
|
|
1575
|
+
plume_group["width"] = containment["width"] = "50%"
|
|
1576
|
+
else:
|
|
1577
|
+
plume_group["width"] = containment["width"] = "100%"
|
|
1578
|
+
elif mark_choice == "plume_group":
|
|
1579
|
+
containment["display"] = "flex"
|
|
1580
|
+
phase["display"] = "flex"
|
|
1581
|
+
phase["width"] = containment["width"] = "50%"
|
|
1009
1582
|
elif mark_choice == "none":
|
|
1010
|
-
|
|
1583
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1011
1584
|
containment["display"] = "flex"
|
|
1012
|
-
phase["width"] = "50%"
|
|
1013
1585
|
phase["display"] = "flex"
|
|
1586
|
+
n_categories = 2 + has_plume_groups
|
|
1587
|
+
if n_categories == 3:
|
|
1588
|
+
plume_group["width"] = containment["width"] = phase["width"] = "33%"
|
|
1589
|
+
elif n_categories == 2:
|
|
1590
|
+
plume_group["width"] = containment["width"] = phase["width"] = "50%"
|
|
1591
|
+
else:
|
|
1592
|
+
plume_group["width"] = containment["width"] = phase["width"] = "100%"
|
|
1014
1593
|
else: # mark == "containment"
|
|
1594
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1015
1595
|
phase["display"] = "flex"
|
|
1016
|
-
|
|
1596
|
+
n_categories = 1 + has_plume_groups
|
|
1597
|
+
if n_categories == 2:
|
|
1598
|
+
plume_group["width"] = phase["width"] = "50%"
|
|
1599
|
+
else:
|
|
1600
|
+
plume_group["width"] = phase["width"] = "100%"
|
|
1601
|
+
return [zone, region, phase, containment, plume_group]
|