webviz-subsurface 0.2.36__py3-none-any.whl → 0.2.37__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- webviz_subsurface/__init__.py +1 -1
- webviz_subsurface/_components/color_picker.py +1 -1
- webviz_subsurface/_providers/ensemble_polygon_provider/__init__.py +3 -0
- webviz_subsurface/_providers/ensemble_polygon_provider/_polygon_discovery.py +97 -0
- webviz_subsurface/_providers/ensemble_polygon_provider/_provider_impl_file.py +226 -0
- webviz_subsurface/_providers/ensemble_polygon_provider/ensemble_polygon_provider.py +53 -0
- webviz_subsurface/_providers/ensemble_polygon_provider/ensemble_polygon_provider_factory.py +99 -0
- webviz_subsurface/_providers/ensemble_polygon_provider/polygon_server.py +125 -0
- webviz_subsurface/plugins/_co2_leakage/_plugin.py +531 -377
- webviz_subsurface/plugins/_co2_leakage/_utilities/_misc.py +9 -0
- webviz_subsurface/plugins/_co2_leakage/_utilities/callbacks.py +169 -173
- webviz_subsurface/plugins/_co2_leakage/_utilities/co2volume.py +329 -84
- webviz_subsurface/plugins/_co2_leakage/_utilities/containment_data_provider.py +147 -0
- webviz_subsurface/plugins/_co2_leakage/_utilities/ensemble_well_picks.py +105 -0
- webviz_subsurface/plugins/_co2_leakage/_utilities/generic.py +170 -2
- webviz_subsurface/plugins/_co2_leakage/_utilities/initialization.py +189 -96
- webviz_subsurface/plugins/_co2_leakage/_utilities/polygon_handler.py +60 -0
- webviz_subsurface/plugins/_co2_leakage/_utilities/summary_graphs.py +77 -173
- webviz_subsurface/plugins/_co2_leakage/_utilities/surface_publishing.py +29 -21
- webviz_subsurface/plugins/_co2_leakage/_utilities/unsmry_data_provider.py +108 -0
- webviz_subsurface/plugins/_co2_leakage/views/mainview/mainview.py +30 -18
- webviz_subsurface/plugins/_co2_leakage/views/mainview/settings.py +805 -343
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/METADATA +2 -2
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/RECORD +30 -19
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/WHEEL +1 -1
- /webviz_subsurface/plugins/_co2_leakage/_utilities/{fault_polygons.py → fault_polygons_handler.py} +0 -0
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/LICENSE +0 -0
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/LICENSE.chromedriver +0 -0
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/entry_points.txt +0 -0
- {webviz_subsurface-0.2.36.dist-info → webviz_subsurface-0.2.37.dist-info}/top_level.txt +0 -0
|
@@ -15,10 +15,17 @@ from webviz_subsurface._providers.ensemble_surface_provider.ensemble_surface_pro
|
|
|
15
15
|
from webviz_subsurface.plugins._co2_leakage._utilities.callbacks import property_origin
|
|
16
16
|
from webviz_subsurface.plugins._co2_leakage._utilities.generic import (
|
|
17
17
|
Co2MassScale,
|
|
18
|
+
Co2VolumeScale,
|
|
19
|
+
FilteredMapAttribute,
|
|
18
20
|
GraphSource,
|
|
19
21
|
LayoutLabels,
|
|
20
22
|
LayoutStyle,
|
|
21
23
|
MapAttribute,
|
|
24
|
+
MapGroup,
|
|
25
|
+
MapThresholds,
|
|
26
|
+
MapType,
|
|
27
|
+
MenuOptions,
|
|
28
|
+
map_group_labels,
|
|
22
29
|
)
|
|
23
30
|
|
|
24
31
|
|
|
@@ -33,6 +40,7 @@ class ViewSettings(SettingsGroupABC):
|
|
|
33
40
|
FORMATION = "formation"
|
|
34
41
|
ENSEMBLE = "ensemble"
|
|
35
42
|
REALIZATION = "realization"
|
|
43
|
+
ALL_REAL = "all-realizations"
|
|
36
44
|
|
|
37
45
|
PROPERTY = "property"
|
|
38
46
|
STATISTIC = "statistic"
|
|
@@ -48,6 +56,8 @@ class ViewSettings(SettingsGroupABC):
|
|
|
48
56
|
Y_MAX_GRAPH = "y-max-graph"
|
|
49
57
|
Y_MIN_AUTO_GRAPH = "y-min-auto-graph"
|
|
50
58
|
Y_MAX_AUTO_GRAPH = "y-max-auto-graph"
|
|
59
|
+
Y_LIM_OPTIONS = "y_limit_options"
|
|
60
|
+
REAL_OR_STAT = "realization-or-statistics"
|
|
51
61
|
COLOR_BY = "color-by"
|
|
52
62
|
MARK_BY = "mark-by"
|
|
53
63
|
SORT_PLOT = "sort-plot"
|
|
@@ -59,120 +69,159 @@ class ViewSettings(SettingsGroupABC):
|
|
|
59
69
|
PHASE = "phase"
|
|
60
70
|
PHASE_MENU = "phase-menu"
|
|
61
71
|
CONTAINMENT = "containment"
|
|
72
|
+
PLUME_GROUP = "plume-group"
|
|
62
73
|
CONTAINMENT_MENU = "containment-menu"
|
|
74
|
+
PLUME_GROUP_MENU = "plume-group-menu"
|
|
75
|
+
DATE_OPTION = "date-option"
|
|
76
|
+
DATE_OPTION_COL = "date-option-column"
|
|
63
77
|
|
|
64
78
|
PLUME_THRESHOLD = "plume-threshold"
|
|
65
79
|
PLUME_SMOOTHING = "plume-smoothing"
|
|
66
80
|
|
|
67
|
-
VISUALIZATION_THRESHOLD = "visualization-threshold"
|
|
68
81
|
VISUALIZATION_UPDATE = "visualization-update"
|
|
82
|
+
VISUALIZATION_THRESHOLD_BUTTON = "visualization-threshold-button"
|
|
83
|
+
VISUALIZATION_THRESHOLD_DIALOG = "visualization-threshold-dialog"
|
|
69
84
|
MASS_UNIT = "mass-unit"
|
|
85
|
+
MASS_UNIT_UPDATE = "mass-unit-update"
|
|
70
86
|
|
|
71
87
|
FEEDBACK_BUTTON = "feedback-button"
|
|
72
88
|
FEEDBACK = "feedback"
|
|
73
89
|
|
|
90
|
+
# pylint: disable=too-many-arguments
|
|
74
91
|
def __init__(
|
|
75
92
|
self,
|
|
76
93
|
ensemble_paths: Dict[str, str],
|
|
94
|
+
realizations_per_ensemble: Dict[str, List[int]],
|
|
77
95
|
ensemble_surface_providers: Dict[str, EnsembleSurfaceProvider],
|
|
78
96
|
initial_surface: Optional[str],
|
|
79
|
-
map_attribute_names:
|
|
97
|
+
map_attribute_names: FilteredMapAttribute,
|
|
98
|
+
map_thresholds: MapThresholds,
|
|
80
99
|
color_scale_names: List[str],
|
|
81
100
|
well_names_dict: Dict[str, List[str]],
|
|
82
|
-
menu_options: Dict[str, Dict[
|
|
101
|
+
menu_options: Dict[str, Dict[GraphSource, MenuOptions]],
|
|
102
|
+
content: Dict[str, bool],
|
|
83
103
|
):
|
|
84
104
|
super().__init__("Settings")
|
|
85
105
|
self._ensemble_paths = ensemble_paths
|
|
106
|
+
self._realizations_per_ensemble = realizations_per_ensemble
|
|
86
107
|
self._ensemble_surface_providers = ensemble_surface_providers
|
|
87
108
|
self._map_attribute_names = map_attribute_names
|
|
109
|
+
self._thresholds = map_thresholds
|
|
110
|
+
self._threshold_ids = list(self._thresholds.standard_thresholds.keys())
|
|
88
111
|
self._color_scale_names = color_scale_names
|
|
89
112
|
self._initial_surface = initial_surface
|
|
90
113
|
self._well_names_dict = well_names_dict
|
|
91
114
|
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
|
-
)
|
|
115
|
+
self._content = content
|
|
102
116
|
|
|
103
117
|
def layout(self) -> List[Component]:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
118
|
+
menu_layout = []
|
|
119
|
+
if self._content["maps"]:
|
|
120
|
+
menu_layout += [
|
|
121
|
+
DialogLayout(self._well_names_dict, list(self._ensemble_paths.keys())),
|
|
122
|
+
OpenDialogButton(),
|
|
123
|
+
]
|
|
124
|
+
menu_layout.append(
|
|
107
125
|
EnsembleSelectorLayout(
|
|
108
126
|
self.register_component_unique_id(self.Ids.ENSEMBLE),
|
|
109
127
|
self.register_component_unique_id(self.Ids.REALIZATION),
|
|
128
|
+
self.register_component_unique_id(self.Ids.ALL_REAL),
|
|
110
129
|
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
|
-
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
if self._content["maps"]:
|
|
133
|
+
menu_layout += [
|
|
134
|
+
FilterSelectorLayout(
|
|
135
|
+
self.register_component_unique_id(self.Ids.FORMATION)
|
|
136
|
+
),
|
|
137
|
+
VisualizationThresholdsLayout(
|
|
138
|
+
self._threshold_ids,
|
|
139
|
+
self._thresholds,
|
|
140
|
+
self.register_component_unique_id(self.Ids.VISUALIZATION_UPDATE),
|
|
141
|
+
),
|
|
142
|
+
MapSelectorLayout(
|
|
143
|
+
self._color_scale_names,
|
|
144
|
+
self.register_component_unique_id(self.Ids.PROPERTY),
|
|
145
|
+
self.register_component_unique_id(self.Ids.STATISTIC),
|
|
146
|
+
self.register_component_unique_id(self.Ids.COLOR_SCALE),
|
|
147
|
+
self.register_component_unique_id(self.Ids.CM_MIN),
|
|
148
|
+
self.register_component_unique_id(self.Ids.CM_MAX),
|
|
149
|
+
self.register_component_unique_id(self.Ids.CM_MIN_AUTO),
|
|
150
|
+
self.register_component_unique_id(self.Ids.CM_MAX_AUTO),
|
|
151
|
+
self.register_component_unique_id(self.Ids.MASS_UNIT),
|
|
152
|
+
self.register_component_unique_id(self.Ids.MASS_UNIT_UPDATE),
|
|
153
|
+
self._map_attribute_names,
|
|
154
|
+
),
|
|
155
|
+
]
|
|
156
|
+
if self._content["any_table"]:
|
|
157
|
+
menu_layout.append(
|
|
158
|
+
GraphSelectorsLayout(
|
|
159
|
+
self.register_component_unique_id(self.Ids.GRAPH_SOURCE),
|
|
160
|
+
self.register_component_unique_id(self.Ids.CO2_SCALE),
|
|
161
|
+
[
|
|
162
|
+
self.register_component_unique_id(self.Ids.Y_MIN_GRAPH),
|
|
163
|
+
self.register_component_unique_id(self.Ids.Y_MIN_AUTO_GRAPH),
|
|
164
|
+
],
|
|
165
|
+
[
|
|
166
|
+
self.register_component_unique_id(self.Ids.Y_MAX_GRAPH),
|
|
167
|
+
self.register_component_unique_id(self.Ids.Y_MAX_AUTO_GRAPH),
|
|
168
|
+
],
|
|
169
|
+
[
|
|
170
|
+
self.register_component_unique_id(self.Ids.COLOR_BY),
|
|
171
|
+
self.register_component_unique_id(self.Ids.MARK_BY),
|
|
172
|
+
self.register_component_unique_id(self.Ids.SORT_PLOT),
|
|
173
|
+
self.register_component_unique_id(self.Ids.ZONE),
|
|
174
|
+
self.register_component_unique_id(self.Ids.ZONE_COL),
|
|
175
|
+
self.register_component_unique_id(self.Ids.REGION),
|
|
176
|
+
self.register_component_unique_id(self.Ids.REGION_COL),
|
|
177
|
+
self.register_component_unique_id(self.Ids.ZONE_REGION),
|
|
178
|
+
self.register_component_unique_id(self.Ids.PHASE),
|
|
179
|
+
self.register_component_unique_id(self.Ids.PHASE_MENU),
|
|
180
|
+
self.register_component_unique_id(self.Ids.CONTAINMENT),
|
|
181
|
+
self.register_component_unique_id(self.Ids.CONTAINMENT_MENU),
|
|
182
|
+
self.register_component_unique_id(self.Ids.PLUME_GROUP),
|
|
183
|
+
self.register_component_unique_id(self.Ids.PLUME_GROUP_MENU),
|
|
184
|
+
self.register_component_unique_id(self.Ids.REAL_OR_STAT),
|
|
185
|
+
self.register_component_unique_id(self.Ids.Y_LIM_OPTIONS),
|
|
186
|
+
self.register_component_unique_id(self.Ids.DATE_OPTION),
|
|
187
|
+
self.register_component_unique_id(self.Ids.DATE_OPTION_COL),
|
|
188
|
+
],
|
|
189
|
+
self._content,
|
|
190
|
+
)
|
|
191
|
+
)
|
|
192
|
+
if self._content["maps"]:
|
|
193
|
+
menu_layout.append(
|
|
194
|
+
ExperimentalFeaturesLayout(
|
|
195
|
+
self.register_component_unique_id(self.Ids.PLUME_THRESHOLD),
|
|
196
|
+
self.register_component_unique_id(self.Ids.PLUME_SMOOTHING),
|
|
197
|
+
),
|
|
198
|
+
)
|
|
199
|
+
menu_layout += [
|
|
158
200
|
FeedbackLayout(),
|
|
159
201
|
FeedbackButton(),
|
|
160
202
|
]
|
|
203
|
+
return menu_layout
|
|
161
204
|
|
|
205
|
+
# pylint: disable=too-many-statements
|
|
162
206
|
def set_callbacks(self) -> None:
|
|
207
|
+
# pylint: disable=unused-argument
|
|
163
208
|
@callback(
|
|
164
209
|
Output(
|
|
165
210
|
self.component_unique_id(self.Ids.REALIZATION).to_string(), "options"
|
|
166
211
|
),
|
|
167
212
|
Output(self.component_unique_id(self.Ids.REALIZATION).to_string(), "value"),
|
|
168
213
|
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
214
|
+
Input(self.component_unique_id(self.Ids.ALL_REAL).to_string(), "n_clicks"),
|
|
169
215
|
)
|
|
170
|
-
def set_realizations(
|
|
216
|
+
def set_realizations(
|
|
217
|
+
ensemble: str,
|
|
218
|
+
select_all: int,
|
|
219
|
+
) -> Tuple[List[Dict[str, Any]], List[int]]:
|
|
171
220
|
rlz = [
|
|
172
221
|
{"value": r, "label": str(r)}
|
|
173
|
-
for r in self.
|
|
222
|
+
for r in self._realizations_per_ensemble[ensemble]
|
|
174
223
|
]
|
|
175
|
-
return rlz, [
|
|
224
|
+
return rlz, self._realizations_per_ensemble[ensemble] # type: ignore
|
|
176
225
|
|
|
177
226
|
@callback(
|
|
178
227
|
Output(self.component_unique_id(self.Ids.FORMATION).to_string(), "options"),
|
|
@@ -193,10 +242,7 @@ class ViewSettings(SettingsGroupABC):
|
|
|
193
242
|
if len(surfaces) == 0:
|
|
194
243
|
warning = f"Surface not found for property: {prop}.\n"
|
|
195
244
|
warning += f"Expected name: <formation>--{prop_name}"
|
|
196
|
-
if MapAttribute(prop)
|
|
197
|
-
MapAttribute.MIGRATION_TIME_SGAS,
|
|
198
|
-
MapAttribute.MIGRATION_TIME_AMFG,
|
|
199
|
-
]:
|
|
245
|
+
if MapType[MapAttribute(prop).name].value != "MIGRATION_TIME":
|
|
200
246
|
warning += "--<date>"
|
|
201
247
|
warnings.warn(warning + ".gri")
|
|
202
248
|
# Formation names
|
|
@@ -215,181 +261,300 @@ class ViewSettings(SettingsGroupABC):
|
|
|
215
261
|
)
|
|
216
262
|
return formations, picked_formation
|
|
217
263
|
|
|
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
|
|
264
|
+
if self._content["maps"]:
|
|
234
265
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
266
|
+
@callback(
|
|
267
|
+
Output(
|
|
268
|
+
self.component_unique_id(self.Ids.STATISTIC).to_string(), "disabled"
|
|
269
|
+
),
|
|
270
|
+
Input(
|
|
271
|
+
self.component_unique_id(self.Ids.REALIZATION).to_string(), "value"
|
|
272
|
+
),
|
|
273
|
+
Input(self.component_unique_id(self.Ids.PROPERTY).to_string(), "value"),
|
|
274
|
+
)
|
|
275
|
+
def toggle_statistics(realizations: List[int], attribute: str) -> bool:
|
|
276
|
+
if len(realizations) <= 1:
|
|
277
|
+
return True
|
|
278
|
+
if MapType[MapAttribute(attribute).name].value == "PLUME":
|
|
279
|
+
return True
|
|
280
|
+
return False
|
|
245
281
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
282
|
+
@callback(
|
|
283
|
+
Output(
|
|
284
|
+
self.component_unique_id(self.Ids.CM_MIN).to_string(), "disabled"
|
|
285
|
+
),
|
|
286
|
+
Output(
|
|
287
|
+
self.component_unique_id(self.Ids.CM_MAX).to_string(), "disabled"
|
|
288
|
+
),
|
|
289
|
+
Input(
|
|
290
|
+
self.component_unique_id(self.Ids.CM_MIN_AUTO).to_string(), "value"
|
|
291
|
+
),
|
|
292
|
+
Input(
|
|
293
|
+
self.component_unique_id(self.Ids.CM_MAX_AUTO).to_string(), "value"
|
|
294
|
+
),
|
|
295
|
+
)
|
|
296
|
+
def set_color_range_data(
|
|
297
|
+
min_auto: List[str], max_auto: List[str]
|
|
298
|
+
) -> Tuple[bool, bool]:
|
|
299
|
+
return len(min_auto) == 1, len(max_auto) == 1
|
|
258
300
|
|
|
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
|
|
301
|
+
@callback(
|
|
302
|
+
Output(
|
|
303
|
+
self.component_unique_id(self.Ids.MASS_UNIT).to_string(), "disabled"
|
|
304
|
+
),
|
|
305
|
+
Input(self.component_unique_id(self.Ids.PROPERTY).to_string(), "value"),
|
|
306
|
+
)
|
|
307
|
+
def toggle_unit(attribute: str) -> bool:
|
|
308
|
+
if MapType[MapAttribute(attribute).name].value != "MASS":
|
|
309
|
+
return True
|
|
310
|
+
return False
|
|
277
311
|
|
|
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"
|
|
312
|
+
if self._content["any_table"]:
|
|
295
313
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
+
@callback(
|
|
315
|
+
Output(
|
|
316
|
+
self.component_unique_id(self.Ids.Y_MIN_GRAPH).to_string(),
|
|
317
|
+
"disabled",
|
|
318
|
+
),
|
|
319
|
+
Output(
|
|
320
|
+
self.component_unique_id(self.Ids.Y_MAX_GRAPH).to_string(),
|
|
321
|
+
"disabled",
|
|
322
|
+
),
|
|
323
|
+
Input(
|
|
324
|
+
self.component_unique_id(self.Ids.Y_MIN_AUTO_GRAPH).to_string(),
|
|
325
|
+
"value",
|
|
326
|
+
),
|
|
327
|
+
Input(
|
|
328
|
+
self.component_unique_id(self.Ids.Y_MAX_AUTO_GRAPH).to_string(),
|
|
329
|
+
"value",
|
|
330
|
+
),
|
|
331
|
+
)
|
|
332
|
+
def set_y_min_max(
|
|
333
|
+
min_auto: List[str], max_auto: List[str]
|
|
334
|
+
) -> Tuple[bool, bool]:
|
|
335
|
+
return len(min_auto) == 1, len(max_auto) == 1
|
|
314
336
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
if
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
337
|
+
@callback(
|
|
338
|
+
Output(self.component_unique_id(self.Ids.PHASE).to_string(), "options"),
|
|
339
|
+
Output(self.component_unique_id(self.Ids.PHASE).to_string(), "value"),
|
|
340
|
+
Input(
|
|
341
|
+
self.component_unique_id(self.Ids.GRAPH_SOURCE).to_string(), "value"
|
|
342
|
+
),
|
|
343
|
+
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
344
|
+
State(self.component_unique_id(self.Ids.PHASE).to_string(), "value"),
|
|
345
|
+
)
|
|
346
|
+
def set_phases(
|
|
347
|
+
source: GraphSource,
|
|
348
|
+
ensemble: str,
|
|
349
|
+
current_value: str,
|
|
350
|
+
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
351
|
+
if ensemble is not None:
|
|
352
|
+
phases = self._menu_options[ensemble][source]["phases"]
|
|
353
|
+
options = [
|
|
354
|
+
{"label": phase.title(), "value": phase} for phase in phases
|
|
355
|
+
]
|
|
356
|
+
return options, no_update if current_value in phases else "total"
|
|
357
|
+
return [{"label": "Total", "value": "total"}], "total"
|
|
333
358
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
self.component_unique_id(self.Ids.
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
359
|
+
@callback(
|
|
360
|
+
Output(self.component_unique_id(self.Ids.ZONE).to_string(), "options"),
|
|
361
|
+
Output(self.component_unique_id(self.Ids.ZONE).to_string(), "value"),
|
|
362
|
+
Input(
|
|
363
|
+
self.component_unique_id(self.Ids.GRAPH_SOURCE).to_string(), "value"
|
|
364
|
+
),
|
|
365
|
+
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
366
|
+
State(self.component_unique_id(self.Ids.ZONE).to_string(), "value"),
|
|
367
|
+
)
|
|
368
|
+
def set_zones(
|
|
369
|
+
source: GraphSource,
|
|
370
|
+
ensemble: str,
|
|
371
|
+
current_value: str,
|
|
372
|
+
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
373
|
+
if ensemble is not None:
|
|
374
|
+
zones = self._menu_options[ensemble][source]["zones"]
|
|
375
|
+
if len(zones) > 0:
|
|
376
|
+
options = [
|
|
377
|
+
{"label": zone.title(), "value": zone} for zone in zones
|
|
378
|
+
]
|
|
379
|
+
return options, no_update if current_value in zones else "all"
|
|
380
|
+
return [{"label": "All", "value": "all"}], "all"
|
|
348
381
|
|
|
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
|
|
382
|
+
@callback(
|
|
383
|
+
Output(
|
|
384
|
+
self.component_unique_id(self.Ids.REGION).to_string(), "options"
|
|
385
|
+
),
|
|
386
|
+
Output(self.component_unique_id(self.Ids.REGION).to_string(), "value"),
|
|
387
|
+
Input(
|
|
388
|
+
self.component_unique_id(self.Ids.GRAPH_SOURCE).to_string(), "value"
|
|
389
|
+
),
|
|
390
|
+
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
391
|
+
State(self.component_unique_id(self.Ids.REGION).to_string(), "value"),
|
|
382
392
|
)
|
|
383
|
-
|
|
393
|
+
def set_regions(
|
|
394
|
+
source: GraphSource,
|
|
395
|
+
ensemble: str,
|
|
396
|
+
current_value: str,
|
|
397
|
+
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
398
|
+
if ensemble is not None:
|
|
399
|
+
regions = self._menu_options[ensemble][source]["regions"]
|
|
400
|
+
if len(regions) > 0:
|
|
401
|
+
options = [
|
|
402
|
+
{"label": reg.title(), "value": reg} for reg in regions
|
|
403
|
+
]
|
|
404
|
+
return options, no_update if current_value in regions else "all"
|
|
405
|
+
return [{"label": "All", "value": "all"}], "all"
|
|
384
406
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
407
|
+
@callback(
|
|
408
|
+
Output(
|
|
409
|
+
self.component_unique_id(self.Ids.PLUME_GROUP).to_string(),
|
|
410
|
+
"options",
|
|
411
|
+
),
|
|
412
|
+
Output(
|
|
413
|
+
self.component_unique_id(self.Ids.PLUME_GROUP).to_string(), "value"
|
|
414
|
+
),
|
|
415
|
+
Input(
|
|
416
|
+
self.component_unique_id(self.Ids.GRAPH_SOURCE).to_string(), "value"
|
|
417
|
+
),
|
|
418
|
+
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
419
|
+
State(
|
|
420
|
+
self.component_unique_id(self.Ids.PLUME_GROUP).to_string(), "value"
|
|
421
|
+
),
|
|
422
|
+
)
|
|
423
|
+
def set_plume_groups(
|
|
424
|
+
source: GraphSource,
|
|
425
|
+
ensemble: str,
|
|
426
|
+
current_value: str,
|
|
427
|
+
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
428
|
+
if ensemble is not None:
|
|
429
|
+
plume_groups = self._menu_options[ensemble][source]["plume_groups"]
|
|
430
|
+
if len(plume_groups) > 0:
|
|
431
|
+
options = [
|
|
432
|
+
{"label": x.title(), "value": x} for x in plume_groups
|
|
433
|
+
]
|
|
434
|
+
return (
|
|
435
|
+
options,
|
|
436
|
+
no_update if current_value in plume_groups else "all",
|
|
437
|
+
)
|
|
438
|
+
return [{"label": "All", "value": "all"}], "all"
|
|
439
|
+
|
|
440
|
+
@callback(
|
|
441
|
+
Output(
|
|
442
|
+
self.component_unique_id(self.Ids.DATE_OPTION).to_string(),
|
|
443
|
+
"options",
|
|
444
|
+
),
|
|
445
|
+
Output(
|
|
446
|
+
self.component_unique_id(self.Ids.DATE_OPTION).to_string(), "value"
|
|
447
|
+
),
|
|
448
|
+
Input(
|
|
449
|
+
self.component_unique_id(self.Ids.GRAPH_SOURCE).to_string(), "value"
|
|
450
|
+
),
|
|
451
|
+
Input(self.component_unique_id(self.Ids.ENSEMBLE).to_string(), "value"),
|
|
452
|
+
State(
|
|
453
|
+
self.component_unique_id(self.Ids.DATE_OPTION).to_string(), "value"
|
|
454
|
+
),
|
|
455
|
+
)
|
|
456
|
+
def set_date_option(
|
|
457
|
+
source: GraphSource,
|
|
458
|
+
ensemble: str,
|
|
459
|
+
current_value: str,
|
|
460
|
+
) -> Tuple[List[Dict[str, str]], Union[Any, str]]:
|
|
461
|
+
if ensemble is not None:
|
|
462
|
+
dates = self._menu_options[ensemble][source]["dates"]
|
|
463
|
+
options = [{"label": date.title(), "value": date} for date in dates]
|
|
464
|
+
return options, no_update if current_value in dates else dates[-1]
|
|
465
|
+
return [], None
|
|
466
|
+
|
|
467
|
+
@callback(
|
|
468
|
+
Output(
|
|
469
|
+
self.component_unique_id(self.Ids.MARK_BY).to_string(), "options"
|
|
470
|
+
),
|
|
471
|
+
Output(self.component_unique_id(self.Ids.MARK_BY).to_string(), "value"),
|
|
472
|
+
Output(
|
|
473
|
+
self.component_unique_id(self.Ids.ZONE_COL).to_string(), "style"
|
|
474
|
+
),
|
|
475
|
+
Output(
|
|
476
|
+
self.component_unique_id(self.Ids.REGION_COL).to_string(), "style"
|
|
477
|
+
),
|
|
478
|
+
Output(
|
|
479
|
+
self.component_unique_id(self.Ids.PHASE_MENU).to_string(), "style"
|
|
480
|
+
),
|
|
481
|
+
Output(
|
|
482
|
+
self.component_unique_id(self.Ids.CONTAINMENT_MENU).to_string(),
|
|
483
|
+
"style",
|
|
484
|
+
),
|
|
485
|
+
Output(
|
|
486
|
+
self.component_unique_id(self.Ids.PLUME_GROUP_MENU).to_string(),
|
|
487
|
+
"style",
|
|
488
|
+
),
|
|
489
|
+
Input(self.component_unique_id(self.Ids.COLOR_BY).to_string(), "value"),
|
|
490
|
+
Input(self.component_unique_id(self.Ids.MARK_BY).to_string(), "value"),
|
|
491
|
+
)
|
|
492
|
+
def organize_color_and_mark_menus(
|
|
493
|
+
color_choice: str,
|
|
494
|
+
mark_choice: str,
|
|
495
|
+
) -> Tuple[List[Dict], str, Dict, Dict, Dict, Dict, Dict]:
|
|
496
|
+
mark_options = [
|
|
497
|
+
{"label": "Phase", "value": "phase"},
|
|
498
|
+
{"label": "None", "value": "none"},
|
|
499
|
+
]
|
|
500
|
+
if self._content["zones"] and color_choice == "containment":
|
|
501
|
+
mark_options.append({"label": "Zone", "value": "zone"})
|
|
502
|
+
if self._content["regions"] and color_choice == "containment":
|
|
503
|
+
mark_options.append({"label": "Region", "value": "region"})
|
|
504
|
+
if self._content["plume_groups"] and color_choice == "containment":
|
|
505
|
+
mark_options.append(
|
|
506
|
+
{"label": "Plume group", "value": "plume_group"}
|
|
507
|
+
)
|
|
508
|
+
if color_choice in ["zone", "region", "plume_group"]:
|
|
509
|
+
mark_options.append(
|
|
510
|
+
{"label": "Containment", "value": "containment"}
|
|
511
|
+
)
|
|
512
|
+
if (
|
|
513
|
+
color_choice in ["zone", "region"]
|
|
514
|
+
and self._content["plume_groups"]
|
|
515
|
+
):
|
|
516
|
+
mark_options.append(
|
|
517
|
+
{"label": "Plume group", "value": "plume_group"}
|
|
518
|
+
)
|
|
519
|
+
if color_choice == "plume_group":
|
|
520
|
+
if self._content["zones"]:
|
|
521
|
+
mark_options.append({"label": "Zone", "value": "zone"})
|
|
522
|
+
if self._content["regions"]:
|
|
523
|
+
mark_options.append({"label": "Region", "value": "region"})
|
|
524
|
+
if mark_choice is None or mark_choice == color_choice:
|
|
525
|
+
mark_choice = "phase"
|
|
526
|
+
if mark_choice in ["zone", "region"] and color_choice in [
|
|
527
|
+
"zone",
|
|
528
|
+
"region",
|
|
529
|
+
]:
|
|
530
|
+
mark_choice = "phase"
|
|
531
|
+
zone, region, phase, containment, plume_group = _make_styles(
|
|
532
|
+
color_choice,
|
|
533
|
+
mark_choice,
|
|
534
|
+
self._content["zones"],
|
|
535
|
+
self._content["regions"],
|
|
536
|
+
self._content["plume_groups"],
|
|
537
|
+
)
|
|
538
|
+
return (
|
|
539
|
+
mark_options,
|
|
540
|
+
mark_choice,
|
|
541
|
+
zone,
|
|
542
|
+
region,
|
|
543
|
+
phase,
|
|
544
|
+
containment,
|
|
545
|
+
plume_group,
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
@callback(
|
|
549
|
+
Output(self.component_unique_id(self.Ids.ZONE).to_string(), "disabled"),
|
|
550
|
+
Output(
|
|
551
|
+
self.component_unique_id(self.Ids.REGION).to_string(), "disabled"
|
|
552
|
+
),
|
|
553
|
+
Input(self.component_unique_id(self.Ids.ZONE).to_string(), "value"),
|
|
554
|
+
Input(self.component_unique_id(self.Ids.REGION).to_string(), "value"),
|
|
555
|
+
)
|
|
556
|
+
def disable_zone_or_region(zone: str, region: str) -> Tuple[bool, bool]:
|
|
557
|
+
return region != "all", zone != "all"
|
|
393
558
|
|
|
394
559
|
|
|
395
560
|
class OpenDialogButton(html.Button):
|
|
@@ -484,6 +649,87 @@ class FilterSelectorLayout(wcc.Selectors):
|
|
|
484
649
|
)
|
|
485
650
|
|
|
486
651
|
|
|
652
|
+
class OpenVisualizationThresholdsButton(html.Button):
|
|
653
|
+
def __init__(self) -> None:
|
|
654
|
+
super().__init__(
|
|
655
|
+
LayoutLabels.VISUALIZATION_THRESHOLDS,
|
|
656
|
+
id=ViewSettings.Ids.VISUALIZATION_THRESHOLD_BUTTON,
|
|
657
|
+
style=LayoutStyle.THRESHOLDS_BUTTON,
|
|
658
|
+
n_clicks=0,
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
class VisualizationThresholdsLayout(wcc.Dialog):
|
|
663
|
+
"""Layout for the visualization thresholds dialog"""
|
|
664
|
+
|
|
665
|
+
def __init__(
|
|
666
|
+
self,
|
|
667
|
+
ids: List[str],
|
|
668
|
+
thresholds: MapThresholds,
|
|
669
|
+
visualization_update_id: str,
|
|
670
|
+
) -> None:
|
|
671
|
+
standard_thresholds = thresholds.standard_thresholds
|
|
672
|
+
|
|
673
|
+
fields = [
|
|
674
|
+
html.Div(
|
|
675
|
+
"Here you can select a filter for the visualization of the map, "
|
|
676
|
+
"hiding values smaller than the selected minimum cutoff. "
|
|
677
|
+
"After changing the threshold value, press 'Update' to have the map reappear. "
|
|
678
|
+
"A value of -1 can be used to visualize zeros."
|
|
679
|
+
),
|
|
680
|
+
html.Div("", style={"height": "30px"}),
|
|
681
|
+
html.Div(
|
|
682
|
+
[
|
|
683
|
+
html.Div("Property:", style={"width": "42%"}),
|
|
684
|
+
html.Div("Standard cutoff:", style={"width": "32%"}),
|
|
685
|
+
html.Div("Minimum cutoff:", style={"width": "25%"}),
|
|
686
|
+
],
|
|
687
|
+
style={"display": "flex", "flex-direction": "row"},
|
|
688
|
+
),
|
|
689
|
+
]
|
|
690
|
+
fields += [
|
|
691
|
+
html.Div(
|
|
692
|
+
[
|
|
693
|
+
html.Div(id, style={"width": "42%"}),
|
|
694
|
+
html.Div(standard_thresholds[id], style={"width": "32%"}),
|
|
695
|
+
dcc.Input(
|
|
696
|
+
id=id,
|
|
697
|
+
type="number",
|
|
698
|
+
value=standard_thresholds[id],
|
|
699
|
+
step="0.0005",
|
|
700
|
+
style={"width": "25%"},
|
|
701
|
+
),
|
|
702
|
+
],
|
|
703
|
+
style={"display": "flex", "flex-direction": "row"},
|
|
704
|
+
)
|
|
705
|
+
for id in ids
|
|
706
|
+
]
|
|
707
|
+
fields.append(html.Div(style={"height": "20px"}))
|
|
708
|
+
fields.append(
|
|
709
|
+
html.Div(
|
|
710
|
+
[
|
|
711
|
+
html.Div(style={"width": "80%"}),
|
|
712
|
+
html.Button(
|
|
713
|
+
"Update",
|
|
714
|
+
id=visualization_update_id,
|
|
715
|
+
style=LayoutStyle.VISUALIZATION_BUTTON,
|
|
716
|
+
n_clicks=0,
|
|
717
|
+
),
|
|
718
|
+
],
|
|
719
|
+
style={"display": "flex", "flex-direction": "row"},
|
|
720
|
+
)
|
|
721
|
+
)
|
|
722
|
+
super().__init__(
|
|
723
|
+
title=LayoutLabels.VISUALIZATION_THRESHOLDS,
|
|
724
|
+
id=ViewSettings.Ids.VISUALIZATION_THRESHOLD_DIALOG,
|
|
725
|
+
draggable=True,
|
|
726
|
+
open=False,
|
|
727
|
+
children=html.Div(
|
|
728
|
+
fields, style={"flex-direction": "column", "width": "500px"}
|
|
729
|
+
),
|
|
730
|
+
)
|
|
731
|
+
|
|
732
|
+
|
|
487
733
|
class MapSelectorLayout(wcc.Selectors):
|
|
488
734
|
_CM_RANGE = {
|
|
489
735
|
"display": "flex",
|
|
@@ -501,9 +747,9 @@ class MapSelectorLayout(wcc.Selectors):
|
|
|
501
747
|
cm_max_id: str,
|
|
502
748
|
cm_min_auto_id: str,
|
|
503
749
|
cm_max_auto_id: str,
|
|
504
|
-
visualization_threshold_id: str,
|
|
505
|
-
visualization_update_id: str,
|
|
506
750
|
mass_unit_id: str,
|
|
751
|
+
mass_unit_update_id: str,
|
|
752
|
+
map_attribute_names: FilteredMapAttribute,
|
|
507
753
|
):
|
|
508
754
|
default_colormap = (
|
|
509
755
|
"turbo (Seq)"
|
|
@@ -519,8 +765,8 @@ class MapSelectorLayout(wcc.Selectors):
|
|
|
519
765
|
"Property",
|
|
520
766
|
wcc.Dropdown(
|
|
521
767
|
id=property_id,
|
|
522
|
-
options=_compile_property_options(),
|
|
523
|
-
value=
|
|
768
|
+
options=_compile_property_options(map_attribute_names),
|
|
769
|
+
value=next(iter(map_attribute_names.filtered_values)).value,
|
|
524
770
|
clearable=False,
|
|
525
771
|
),
|
|
526
772
|
"Statistic",
|
|
@@ -568,32 +814,28 @@ class MapSelectorLayout(wcc.Selectors):
|
|
|
568
814
|
],
|
|
569
815
|
style=self._CM_RANGE,
|
|
570
816
|
),
|
|
571
|
-
"
|
|
817
|
+
"Mass unit (for mass maps)",
|
|
572
818
|
html.Div(
|
|
573
819
|
[
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
820
|
+
html.Div(
|
|
821
|
+
wcc.Dropdown(
|
|
822
|
+
id=mass_unit_id,
|
|
823
|
+
options=["kg", "tons", "M tons"],
|
|
824
|
+
value="tons",
|
|
825
|
+
clearable=False,
|
|
826
|
+
),
|
|
827
|
+
style={"width": "50%"},
|
|
579
828
|
),
|
|
580
|
-
html.Div(style={"width": "5%"}),
|
|
581
829
|
html.Button(
|
|
582
|
-
"Update",
|
|
583
|
-
id=
|
|
830
|
+
"Update unit",
|
|
831
|
+
id=mass_unit_update_id,
|
|
584
832
|
style=LayoutStyle.VISUALIZATION_BUTTON,
|
|
585
833
|
n_clicks=0,
|
|
586
834
|
),
|
|
587
835
|
],
|
|
588
836
|
style={"display": "flex"},
|
|
589
837
|
),
|
|
590
|
-
|
|
591
|
-
wcc.Dropdown(
|
|
592
|
-
id=mass_unit_id,
|
|
593
|
-
options=["kg", "tons", "M tons"],
|
|
594
|
-
value="kg",
|
|
595
|
-
clearable=False,
|
|
596
|
-
),
|
|
838
|
+
OpenVisualizationThresholdsButton(),
|
|
597
839
|
],
|
|
598
840
|
)
|
|
599
841
|
],
|
|
@@ -613,40 +855,50 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
613
855
|
y_min_ids: List[str],
|
|
614
856
|
y_max_ids: List[str],
|
|
615
857
|
containment_ids: List[str],
|
|
616
|
-
|
|
617
|
-
has_regions: bool,
|
|
858
|
+
content: Dict[str, bool],
|
|
618
859
|
):
|
|
619
|
-
disp_zone = "flex" if
|
|
620
|
-
disp_region = "flex" if
|
|
621
|
-
|
|
622
|
-
if has_zones and not has_regions:
|
|
623
|
-
header += " zone"
|
|
624
|
-
elif has_regions and not has_zones:
|
|
625
|
-
header += " region"
|
|
860
|
+
disp_zone = "flex" if content["zones"] else "none"
|
|
861
|
+
disp_region = "flex" if content["regions"] else "none"
|
|
862
|
+
disp_plume_group = "flex" if content["plume_groups"] else "none"
|
|
626
863
|
color_options = [{"label": "Containment (standard)", "value": "containment"}]
|
|
627
864
|
mark_options = [{"label": "Phase", "value": "phase"}]
|
|
628
|
-
if
|
|
865
|
+
if content["zones"]:
|
|
629
866
|
color_options.append({"label": "Zone", "value": "zone"})
|
|
630
867
|
mark_options.append({"label": "Zone", "value": "zone"})
|
|
631
|
-
if
|
|
868
|
+
if content["regions"]:
|
|
632
869
|
color_options.append({"label": "Region", "value": "region"})
|
|
633
870
|
mark_options.append({"label": "Region", "value": "region"})
|
|
871
|
+
if content["plume_groups"]:
|
|
872
|
+
color_options.append({"label": "Plume group", "value": "plume_group"})
|
|
873
|
+
mark_options.append({"label": "Plume group", "value": "plume_group"})
|
|
874
|
+
source_options = []
|
|
875
|
+
if content["mass"]:
|
|
876
|
+
source_options.append(GraphSource.CONTAINMENT_MASS)
|
|
877
|
+
if content["volume"]:
|
|
878
|
+
source_options.append(GraphSource.CONTAINMENT_ACTUAL_VOLUME)
|
|
879
|
+
if content["unsmry"]:
|
|
880
|
+
source_options.append(GraphSource.UNSMRY)
|
|
881
|
+
unit_options, init_unit = (
|
|
882
|
+
(list(Co2VolumeScale), Co2VolumeScale.BILLION_CUBIC_METERS)
|
|
883
|
+
if source_options[0] == GraphSource.CONTAINMENT_ACTUAL_VOLUME
|
|
884
|
+
else (list(Co2MassScale), Co2MassScale.MTONS)
|
|
885
|
+
)
|
|
634
886
|
super().__init__(
|
|
635
887
|
label="Graph Settings",
|
|
636
|
-
open_details=
|
|
888
|
+
open_details=not content["maps"],
|
|
637
889
|
children=[
|
|
638
890
|
"Source",
|
|
639
891
|
wcc.Dropdown(
|
|
640
892
|
id=graph_source_id,
|
|
641
|
-
options=
|
|
642
|
-
value=
|
|
893
|
+
options=source_options,
|
|
894
|
+
value=source_options[0],
|
|
643
895
|
clearable=False,
|
|
644
896
|
),
|
|
645
897
|
"Unit",
|
|
646
898
|
wcc.Dropdown(
|
|
647
899
|
id=co2_scale_id,
|
|
648
|
-
options=
|
|
649
|
-
value=
|
|
900
|
+
options=unit_options,
|
|
901
|
+
value=init_unit,
|
|
650
902
|
clearable=False,
|
|
651
903
|
),
|
|
652
904
|
html.Div(
|
|
@@ -683,7 +935,7 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
683
935
|
),
|
|
684
936
|
],
|
|
685
937
|
style={
|
|
686
|
-
"display": "flex",
|
|
938
|
+
"display": "flex",
|
|
687
939
|
"flex-direction": "row",
|
|
688
940
|
"margin-top": "10px",
|
|
689
941
|
"margin-bottom": "1px",
|
|
@@ -712,6 +964,7 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
712
964
|
[
|
|
713
965
|
"Zone",
|
|
714
966
|
wcc.Dropdown(
|
|
967
|
+
options=[{"label": "All", "value": "all"}],
|
|
715
968
|
value="all",
|
|
716
969
|
id=containment_ids[3],
|
|
717
970
|
clearable=False,
|
|
@@ -719,7 +972,18 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
719
972
|
],
|
|
720
973
|
id=containment_ids[4],
|
|
721
974
|
style={
|
|
722
|
-
"width":
|
|
975
|
+
"width": (
|
|
976
|
+
"33%"
|
|
977
|
+
if (content["regions"] and content["plume_groups"])
|
|
978
|
+
else (
|
|
979
|
+
"50%"
|
|
980
|
+
if (
|
|
981
|
+
content["regions"]
|
|
982
|
+
or content["plume_groups"]
|
|
983
|
+
)
|
|
984
|
+
else "100%"
|
|
985
|
+
)
|
|
986
|
+
),
|
|
723
987
|
"display": disp_zone,
|
|
724
988
|
"flex-direction": "column",
|
|
725
989
|
},
|
|
@@ -728,6 +992,7 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
728
992
|
[
|
|
729
993
|
"Region",
|
|
730
994
|
wcc.Dropdown(
|
|
995
|
+
options=[{"label": "All", "value": "all"}],
|
|
731
996
|
value="all",
|
|
732
997
|
id=containment_ids[5],
|
|
733
998
|
clearable=False,
|
|
@@ -735,7 +1000,15 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
735
1000
|
],
|
|
736
1001
|
id=containment_ids[6],
|
|
737
1002
|
style={
|
|
738
|
-
"width":
|
|
1003
|
+
"width": (
|
|
1004
|
+
"33%"
|
|
1005
|
+
if (content["zones"] and content["plume_groups"])
|
|
1006
|
+
else (
|
|
1007
|
+
"50%"
|
|
1008
|
+
if (content["zones"] or content["plume_groups"])
|
|
1009
|
+
else "100%"
|
|
1010
|
+
)
|
|
1011
|
+
),
|
|
739
1012
|
"display": disp_region,
|
|
740
1013
|
"flex-direction": "column",
|
|
741
1014
|
},
|
|
@@ -744,6 +1017,7 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
744
1017
|
[
|
|
745
1018
|
"Phase",
|
|
746
1019
|
wcc.Dropdown(
|
|
1020
|
+
options=[{"label": "Total", "value": "total"}],
|
|
747
1021
|
value="total",
|
|
748
1022
|
clearable=False,
|
|
749
1023
|
id=containment_ids[8],
|
|
@@ -770,37 +1044,105 @@ class GraphSelectorsLayout(wcc.Selectors):
|
|
|
770
1044
|
id=containment_ids[11],
|
|
771
1045
|
style={"display": "none"},
|
|
772
1046
|
),
|
|
1047
|
+
html.Div(
|
|
1048
|
+
[
|
|
1049
|
+
"Plume",
|
|
1050
|
+
wcc.Dropdown(
|
|
1051
|
+
options=[{"label": "All", "value": "all"}],
|
|
1052
|
+
value="all",
|
|
1053
|
+
id=containment_ids[12],
|
|
1054
|
+
clearable=False,
|
|
1055
|
+
),
|
|
1056
|
+
],
|
|
1057
|
+
id=containment_ids[13],
|
|
1058
|
+
style={
|
|
1059
|
+
"width": (
|
|
1060
|
+
"33%"
|
|
1061
|
+
if (content["zones"] and content["regions"])
|
|
1062
|
+
else (
|
|
1063
|
+
"50%"
|
|
1064
|
+
if (content["zones"] or content["regions"])
|
|
1065
|
+
else "100%"
|
|
1066
|
+
)
|
|
1067
|
+
),
|
|
1068
|
+
"display": disp_plume_group,
|
|
1069
|
+
"flex-direction": "column",
|
|
1070
|
+
},
|
|
1071
|
+
),
|
|
773
1072
|
],
|
|
774
1073
|
id=containment_ids[7],
|
|
775
1074
|
style={"display": "flex"},
|
|
776
1075
|
),
|
|
777
1076
|
html.Div(
|
|
778
|
-
"
|
|
1077
|
+
"Time plot options:",
|
|
779
1078
|
style={"margin-top": "10px"},
|
|
780
1079
|
),
|
|
781
|
-
"Minimum",
|
|
782
1080
|
html.Div(
|
|
783
1081
|
[
|
|
784
|
-
dcc.
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1082
|
+
dcc.RadioItems(
|
|
1083
|
+
options=[
|
|
1084
|
+
{"label": "Realizations", "value": "real"},
|
|
1085
|
+
{"label": "Mean/P10/P90", "value": "stat"},
|
|
1086
|
+
],
|
|
1087
|
+
value="real",
|
|
1088
|
+
id=containment_ids[14],
|
|
1089
|
+
inline=True,
|
|
789
1090
|
),
|
|
790
1091
|
],
|
|
791
|
-
style=
|
|
1092
|
+
style={
|
|
1093
|
+
"display": "flex",
|
|
1094
|
+
"flex-direction": "row",
|
|
1095
|
+
},
|
|
1096
|
+
),
|
|
1097
|
+
html.Div(
|
|
1098
|
+
"State at date:",
|
|
1099
|
+
style={"margin-top": "8"},
|
|
792
1100
|
),
|
|
793
|
-
"Maximum",
|
|
794
1101
|
html.Div(
|
|
795
1102
|
[
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
["Auto"],
|
|
800
|
-
id=y_max_ids[1],
|
|
1103
|
+
wcc.Dropdown(
|
|
1104
|
+
id=containment_ids[16],
|
|
1105
|
+
clearable=False,
|
|
801
1106
|
),
|
|
802
1107
|
],
|
|
803
|
-
|
|
1108
|
+
id=containment_ids[17],
|
|
1109
|
+
style={
|
|
1110
|
+
"width": "100%",
|
|
1111
|
+
"flex-direction": "row",
|
|
1112
|
+
},
|
|
1113
|
+
),
|
|
1114
|
+
html.Div(
|
|
1115
|
+
[
|
|
1116
|
+
"Fix minimum y-value",
|
|
1117
|
+
html.Div(
|
|
1118
|
+
[
|
|
1119
|
+
dcc.Input(id=y_min_ids[0], type="number"),
|
|
1120
|
+
dcc.Checklist(
|
|
1121
|
+
["Auto"],
|
|
1122
|
+
["Auto"],
|
|
1123
|
+
id=y_min_ids[1],
|
|
1124
|
+
),
|
|
1125
|
+
],
|
|
1126
|
+
style=self._CM_RANGE,
|
|
1127
|
+
),
|
|
1128
|
+
"Fix maximum y-value",
|
|
1129
|
+
html.Div(
|
|
1130
|
+
[
|
|
1131
|
+
dcc.Input(id=y_max_ids[0], type="number"),
|
|
1132
|
+
dcc.Checklist(
|
|
1133
|
+
["Auto"],
|
|
1134
|
+
["Auto"],
|
|
1135
|
+
id=y_max_ids[1],
|
|
1136
|
+
),
|
|
1137
|
+
],
|
|
1138
|
+
style=self._CM_RANGE,
|
|
1139
|
+
),
|
|
1140
|
+
],
|
|
1141
|
+
style={
|
|
1142
|
+
"display": "flex",
|
|
1143
|
+
"flex-direction": "column",
|
|
1144
|
+
},
|
|
1145
|
+
id=containment_ids[15],
|
|
804
1146
|
),
|
|
805
1147
|
],
|
|
806
1148
|
)
|
|
@@ -848,7 +1190,13 @@ class ExperimentalFeaturesLayout(wcc.Selectors):
|
|
|
848
1190
|
|
|
849
1191
|
|
|
850
1192
|
class EnsembleSelectorLayout(wcc.Selectors):
|
|
851
|
-
def __init__(
|
|
1193
|
+
def __init__(
|
|
1194
|
+
self,
|
|
1195
|
+
ensemble_id: str,
|
|
1196
|
+
realization_id: str,
|
|
1197
|
+
all_real_id: str,
|
|
1198
|
+
ensembles: List[str],
|
|
1199
|
+
):
|
|
852
1200
|
super().__init__(
|
|
853
1201
|
label="Ensemble",
|
|
854
1202
|
open_details=True,
|
|
@@ -860,7 +1208,23 @@ class EnsembleSelectorLayout(wcc.Selectors):
|
|
|
860
1208
|
value=ensembles[0],
|
|
861
1209
|
clearable=False,
|
|
862
1210
|
),
|
|
863
|
-
|
|
1211
|
+
html.Div(
|
|
1212
|
+
[
|
|
1213
|
+
html.Div("Realization", style={"width": "50%"}),
|
|
1214
|
+
html.Button(
|
|
1215
|
+
"Select all",
|
|
1216
|
+
id=all_real_id,
|
|
1217
|
+
style=LayoutStyle.ALL_REAL_BUTTON,
|
|
1218
|
+
n_clicks=0,
|
|
1219
|
+
),
|
|
1220
|
+
],
|
|
1221
|
+
style={
|
|
1222
|
+
"display": "flex",
|
|
1223
|
+
"flex-direction": "row",
|
|
1224
|
+
"margin-top": "3px",
|
|
1225
|
+
"margin-bottom": "3px",
|
|
1226
|
+
},
|
|
1227
|
+
),
|
|
864
1228
|
wcc.SelectWithLabel(
|
|
865
1229
|
id=realization_id,
|
|
866
1230
|
value=[],
|
|
@@ -870,44 +1234,34 @@ class EnsembleSelectorLayout(wcc.Selectors):
|
|
|
870
1234
|
)
|
|
871
1235
|
|
|
872
1236
|
|
|
873
|
-
def
|
|
1237
|
+
def _create_left_side_menu(
|
|
1238
|
+
map_group: str, map_attribute_names: FilteredMapAttribute
|
|
1239
|
+
) -> List:
|
|
1240
|
+
title = {
|
|
1241
|
+
"label": html.Span([f"{map_group}:"], style={"text-decoration": "underline"}),
|
|
1242
|
+
"value": "",
|
|
1243
|
+
"disabled": True,
|
|
1244
|
+
}
|
|
1245
|
+
map_attribute_list = [
|
|
1246
|
+
{"label": MapAttribute[key.name].value, "value": MapAttribute[key.name].value}
|
|
1247
|
+
for key in map_attribute_names.filtered_values.keys()
|
|
1248
|
+
if map_group_labels[MapGroup[key.name].value] == map_group
|
|
1249
|
+
]
|
|
1250
|
+
return [title] + map_attribute_list
|
|
1251
|
+
|
|
1252
|
+
|
|
1253
|
+
def _compile_property_options(
|
|
1254
|
+
map_attribute_names: FilteredMapAttribute,
|
|
1255
|
+
) -> List[Dict[str, Any]]:
|
|
1256
|
+
requested_map_groups = [
|
|
1257
|
+
map_group_labels[MapGroup[key.name].value]
|
|
1258
|
+
for key in map_attribute_names.filtered_values.keys()
|
|
1259
|
+
]
|
|
1260
|
+
unique_requested_map_groups = list(set(requested_map_groups))
|
|
874
1261
|
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},
|
|
1262
|
+
element
|
|
1263
|
+
for group in unique_requested_map_groups
|
|
1264
|
+
for element in _create_left_side_menu(group, map_attribute_names)
|
|
911
1265
|
]
|
|
912
1266
|
|
|
913
1267
|
|
|
@@ -962,7 +1316,7 @@ def get_emails() -> str:
|
|
|
962
1316
|
for i, m in enumerate(
|
|
963
1317
|
[
|
|
964
1318
|
"GLLNAdpthons/bnl",
|
|
965
|
-
"
|
|
1319
|
+
"`ijBgswklmp,amo",
|
|
966
1320
|
"pfhCmq-ml",
|
|
967
1321
|
"bjarnajDjv*jk",
|
|
968
1322
|
"vlfdfmdEkw+kj",
|
|
@@ -972,45 +1326,153 @@ def get_emails() -> str:
|
|
|
972
1326
|
return ";".join(emails[:2]) + "?cc=" + ";".join(emails[2:])
|
|
973
1327
|
|
|
974
1328
|
|
|
1329
|
+
# pylint: disable=too-many-statements, too-many-branches
|
|
975
1330
|
def _make_styles(
|
|
976
1331
|
color_choice: str,
|
|
977
1332
|
mark_choice: str,
|
|
978
1333
|
has_zones: bool,
|
|
979
1334
|
has_regions: bool,
|
|
1335
|
+
has_plume_groups: bool,
|
|
980
1336
|
) -> List[Dict[str, str]]:
|
|
981
1337
|
zone = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
982
1338
|
region = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
983
1339
|
phase = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
984
1340
|
containment = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
1341
|
+
plume_group = {"display": "none", "flex-direction": "column", "width": "100%"}
|
|
985
1342
|
if color_choice == "containment":
|
|
986
1343
|
if mark_choice == "phase":
|
|
987
|
-
zone["width"] = "50%" if has_regions else "100%"
|
|
988
1344
|
zone["display"] = "flex" if has_zones else "none"
|
|
989
|
-
region["width"] = "50%" if has_zones else "100%"
|
|
990
1345
|
region["display"] = "flex" if has_regions else "none"
|
|
1346
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1347
|
+
n_categories = has_regions + has_zones + has_plume_groups
|
|
1348
|
+
if n_categories == 3:
|
|
1349
|
+
zone["width"] = region["width"] = plume_group["width"] = "33%"
|
|
1350
|
+
elif n_categories == 2:
|
|
1351
|
+
zone["width"] = region["width"] = plume_group["width"] = "50%"
|
|
1352
|
+
else:
|
|
1353
|
+
zone["width"] = region["width"] = plume_group["width"] = "100%"
|
|
1354
|
+
elif mark_choice == "plume_group":
|
|
1355
|
+
zone["display"] = "flex" if has_zones else "none"
|
|
1356
|
+
region["display"] = "flex" if has_regions else "none"
|
|
1357
|
+
phase["display"] = "flex"
|
|
1358
|
+
n_categories = 1 + has_regions + has_zones
|
|
1359
|
+
if n_categories == 3:
|
|
1360
|
+
zone["width"] = region["width"] = phase["width"] = "33%"
|
|
1361
|
+
elif n_categories == 2:
|
|
1362
|
+
zone["width"] = region["width"] = phase["width"] = "50%"
|
|
1363
|
+
else:
|
|
1364
|
+
zone["width"] = region["width"] = phase["width"] = "100%"
|
|
991
1365
|
elif mark_choice == "none":
|
|
992
|
-
zone["width"] = "33%" if has_regions else "50%"
|
|
993
1366
|
zone["display"] = "flex" if has_zones else "none"
|
|
994
|
-
region["width"] = "33%" if has_zones else "50%"
|
|
995
1367
|
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
|
-
)
|
|
1368
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1003
1369
|
phase["display"] = "flex"
|
|
1370
|
+
n_categories = 1 + has_regions + has_zones + has_plume_groups
|
|
1371
|
+
if n_categories == 4:
|
|
1372
|
+
phase["width"] = zone["width"] = region["width"] = plume_group[
|
|
1373
|
+
"width"
|
|
1374
|
+
] = "25%"
|
|
1375
|
+
elif n_categories == 3:
|
|
1376
|
+
phase["width"] = zone["width"] = region["width"] = plume_group[
|
|
1377
|
+
"width"
|
|
1378
|
+
] = "33%"
|
|
1379
|
+
elif n_categories == 2:
|
|
1380
|
+
phase["width"] = zone["width"] = region["width"] = plume_group[
|
|
1381
|
+
"width"
|
|
1382
|
+
] = "50%"
|
|
1383
|
+
else:
|
|
1384
|
+
phase["width"] = zone["width"] = region["width"] = plume_group[
|
|
1385
|
+
"width"
|
|
1386
|
+
] = "100%"
|
|
1004
1387
|
else: # mark_choice == "zone" / "region"
|
|
1388
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1389
|
+
n_categories = 1 + has_plume_groups
|
|
1390
|
+
if n_categories == 2:
|
|
1391
|
+
phase["width"] = plume_group["width"] = "50%"
|
|
1392
|
+
else:
|
|
1393
|
+
phase["width"] = plume_group["width"] = "100%"
|
|
1005
1394
|
phase["display"] = "flex"
|
|
1395
|
+
elif color_choice == "plume_group":
|
|
1396
|
+
if mark_choice == "phase":
|
|
1397
|
+
zone["display"] = "flex" if has_zones else "none"
|
|
1398
|
+
region["display"] = "flex" if has_regions else "none"
|
|
1399
|
+
containment["display"] = "flex"
|
|
1400
|
+
n_categories = 1 + has_zones + has_regions
|
|
1401
|
+
if n_categories == 3:
|
|
1402
|
+
zone["width"] = region["width"] = containment["width"] = "33%"
|
|
1403
|
+
elif n_categories == 2:
|
|
1404
|
+
zone["width"] = region["width"] = containment["width"] = "50%"
|
|
1405
|
+
else:
|
|
1406
|
+
zone["width"] = region["width"] = containment["width"] = "100%"
|
|
1407
|
+
elif mark_choice == "containment":
|
|
1408
|
+
zone["display"] = "flex" if has_zones else "none"
|
|
1409
|
+
region["display"] = "flex" if has_regions else "none"
|
|
1410
|
+
phase["display"] = "flex"
|
|
1411
|
+
n_categories = 1 + has_zones + has_regions
|
|
1412
|
+
if n_categories == 3:
|
|
1413
|
+
zone["width"] = region["width"] = phase["width"] = "33%"
|
|
1414
|
+
elif n_categories == 2:
|
|
1415
|
+
zone["width"] = region["width"] = phase["width"] = "50%"
|
|
1416
|
+
else:
|
|
1417
|
+
zone["width"] = region["width"] = phase["width"] = "100%"
|
|
1418
|
+
elif mark_choice == "none":
|
|
1419
|
+
zone["display"] = "flex" if has_zones else "none"
|
|
1420
|
+
region["display"] = "flex" if has_regions else "none"
|
|
1421
|
+
phase["display"] = "flex"
|
|
1422
|
+
containment["display"] = "flex"
|
|
1423
|
+
n_categories = 2 + has_zones + has_regions
|
|
1424
|
+
if n_categories == 4:
|
|
1425
|
+
zone["width"] = region["width"] = phase["width"] = containment[
|
|
1426
|
+
"width"
|
|
1427
|
+
] = "25%"
|
|
1428
|
+
elif n_categories == 3:
|
|
1429
|
+
zone["width"] = region["width"] = phase["width"] = containment[
|
|
1430
|
+
"width"
|
|
1431
|
+
] = "33%"
|
|
1432
|
+
elif n_categories == 2:
|
|
1433
|
+
zone["width"] = region["width"] = phase["width"] = containment[
|
|
1434
|
+
"width"
|
|
1435
|
+
] = "50%"
|
|
1436
|
+
else:
|
|
1437
|
+
zone["width"] = region["width"] = phase["width"] = containment[
|
|
1438
|
+
"width"
|
|
1439
|
+
] = "100%"
|
|
1440
|
+
else: # mark == "zone/region"
|
|
1441
|
+
phase["display"] = "flex"
|
|
1442
|
+
containment["display"] = "flex"
|
|
1443
|
+
phase["width"] = containment["width"] = "50%"
|
|
1444
|
+
elif color_choice == "phase":
|
|
1445
|
+
pass # Not an option
|
|
1006
1446
|
else: # color_choice == "zone" / "region"
|
|
1007
1447
|
if mark_choice == "phase":
|
|
1448
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1008
1449
|
containment["display"] = "flex"
|
|
1450
|
+
n_categories = 1 + has_plume_groups
|
|
1451
|
+
if n_categories == 2:
|
|
1452
|
+
plume_group["width"] = containment["width"] = "50%"
|
|
1453
|
+
else:
|
|
1454
|
+
plume_group["width"] = containment["width"] = "100%"
|
|
1455
|
+
elif mark_choice == "plume_group":
|
|
1456
|
+
containment["display"] = "flex"
|
|
1457
|
+
phase["display"] = "flex"
|
|
1458
|
+
phase["width"] = containment["width"] = "50%"
|
|
1009
1459
|
elif mark_choice == "none":
|
|
1010
|
-
|
|
1460
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1011
1461
|
containment["display"] = "flex"
|
|
1012
|
-
phase["width"] = "50%"
|
|
1013
1462
|
phase["display"] = "flex"
|
|
1463
|
+
n_categories = 2 + has_plume_groups
|
|
1464
|
+
if n_categories == 3:
|
|
1465
|
+
plume_group["width"] = containment["width"] = phase["width"] = "33%"
|
|
1466
|
+
elif n_categories == 2:
|
|
1467
|
+
plume_group["width"] = containment["width"] = phase["width"] = "50%"
|
|
1468
|
+
else:
|
|
1469
|
+
plume_group["width"] = containment["width"] = phase["width"] = "100%"
|
|
1014
1470
|
else: # mark == "containment"
|
|
1471
|
+
plume_group["display"] = "flex" if has_plume_groups else "none"
|
|
1015
1472
|
phase["display"] = "flex"
|
|
1016
|
-
|
|
1473
|
+
n_categories = 1 + has_plume_groups
|
|
1474
|
+
if n_categories == 2:
|
|
1475
|
+
plume_group["width"] = phase["width"] = "50%"
|
|
1476
|
+
else:
|
|
1477
|
+
plume_group["width"] = phase["width"] = "100%"
|
|
1478
|
+
return [zone, region, phase, containment, plume_group]
|