Skip to content

Commit 899bf20

Browse files
committed
save work
1 parent 85bc685 commit 899bf20

File tree

2 files changed

+129
-35
lines changed

2 files changed

+129
-35
lines changed

examples/serve/panels-demo/demo_panels/panel_histo2d.py

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ def render_panel(
127127
)
128128

129129

130+
error_message = ""
131+
132+
130133
@panel.callback(
131134
State("@app", "selectedDatasetId"),
132135
State("@app", "selectedPlaceGeometry"),
@@ -135,7 +138,6 @@ def render_panel(
135138
State("@app", "selectedTimeLabel"),
136139
Input("button", "clicked"),
137140
Output("plot", "chart"),
138-
Output("error_message", "children"),
139141
)
140142
def update_plot(
141143
ctx: Context,
@@ -145,8 +147,8 @@ def update_plot(
145147
var_2_name: str | None = None,
146148
time_label: float | None = None,
147149
_clicked: bool | None = None, # trigger, will always be True
148-
) -> tuple[alt.Chart | None, str]:
149-
150+
) -> alt.Chart | None:
151+
global error_message
150152
dataset = get_dataset(ctx, dataset_id)
151153

152154
if "time" in dataset.coords:
@@ -164,14 +166,13 @@ def update_plot(
164166
place_geometry = shapely.ops.transform(project, place_geometry)
165167

166168
if place_geometry is None or isinstance(place_geometry, shapely.geometry.Point):
167-
return (
168-
None,
169-
"Selected geometry must cover an area.",
170-
)
169+
error_message = "Selected geometry must cover an area."
170+
return None
171171

172172
dataset = mask_dataset_by_geometry(dataset, place_geometry)
173173
if dataset is None:
174-
return None, "Selected geometry produces empty subset"
174+
error_message = "Selected geometry produces empty subset"
175+
return None
175176

176177
var_1_data: np.ndarray = dataset[var_1_name].values.ravel()
177178
var_2_data: np.ndarray = dataset[var_2_name].values.ravel()
@@ -252,7 +253,8 @@ def update_plot(
252253
width="container",
253254
height="container",
254255
)
255-
return chart, ""
256+
error_message = ""
257+
return chart
256258

257259

258260
@panel.callback(
@@ -351,6 +353,7 @@ def show_progress(
351353
@panel.callback(
352354
Input("@app", "selectedDatasetId"),
353355
Input("@app", "selectedPlaceGeometry"),
356+
Input("@app", "selectedTimeLabel"),
354357
State("select_var_1"),
355358
State("select_var_2"),
356359
Input("button", "clicked"),
@@ -360,16 +363,20 @@ def update_error_message(
360363
ctx: Context,
361364
dataset_id: str | None = None,
362365
place_geometry: str | None = None,
366+
_time_label: str | None = None,
363367
var_1_name: str | None = None,
364368
var_2_name: str | None = None,
365369
_clicked: bool | None = None,
366370
) -> str:
367-
dataset = get_dataset(ctx, dataset_id)
368-
if dataset is None:
369-
return "Missing dataset selection"
370-
elif not place_geometry:
371-
return "Missing place geometry selection"
371+
global error_message
372+
373+
if dataset_id is None:
374+
error_message = "Missing dataset selection"
375+
376+
if not place_geometry:
377+
error_message = "Missing place geometry selection"
378+
372379
elif not var_1_name or not var_2_name:
373-
return "Missing variable selection"
374-
else:
375-
return ""
380+
error_message = "Missing variable selection"
381+
382+
return error_message

examples/serve/panels-demo/demo_panels/panel_spectrum.py

Lines changed: 105 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import math
12
from typing import Any
23

34
import altair as alt
@@ -10,7 +11,14 @@
1011
import xarray as xr
1112

1213
from chartlets import Component, Input, State, Output
13-
from chartlets.components import Box, Button, Typography, Select, VegaChart
14+
from chartlets.components import (
15+
Box,
16+
Button,
17+
Typography,
18+
VegaChart,
19+
Radio,
20+
RadioGroup,
21+
)
1422

1523
from xcube.webapi.viewer.contrib import Panel, get_dataset
1624
from xcube.server.api import Context
@@ -21,6 +29,43 @@
2129
panel = Panel(__name__, title="Spectrum View (Demo)", icon="light", position=4)
2230

2331

32+
class DataManager:
33+
def __init__(self):
34+
self.all_data = pd.DataFrame(
35+
columns=["places", "variable", "reflectance", "wavelength"]
36+
)
37+
self.added_places_stack = []
38+
39+
def add_place_data(self, new_data: pd.DataFrame):
40+
if self._is_duplicate(new_data):
41+
print("Duplicate data detected. Not adding.")
42+
print("self.all_data", self.all_data["places"].unique())
43+
print("new_data", new_data["places"].unique())
44+
return
45+
46+
place_names = new_data["places"].unique()
47+
self.all_data = pd.concat([self.all_data, new_data], ignore_index=True)
48+
self.added_places_stack.append(place_names)
49+
50+
def remove_last_added_place(self):
51+
if self.added_places_stack:
52+
last_places = self.added_places_stack.pop()
53+
self.all_data = self.all_data[~self.all_data["places"].isin(last_places)]
54+
55+
def _is_duplicate(self, new_data: pd.DataFrame) -> bool:
56+
merged = new_data.merge(self.all_data, how="left", indicator=True)
57+
return (merged["_merge"] == "both").all()
58+
59+
def delete_all_data(self):
60+
self.all_data = pd.DataFrame(
61+
columns=["places", "variable", "reflectance", "wavelength"]
62+
)
63+
self.added_places_stack = []
64+
65+
66+
manager = DataManager()
67+
68+
2469
@panel.layout(
2570
State("@app", "selectedDatasetId"),
2671
State("@app", "selectedTimeLabel"),
@@ -50,6 +95,15 @@ def render_panel(
5095
text = f"{dataset_id}"
5196
place_text = Typography(id="text", children=[text], align="left")
5297

98+
active_radio = Radio(id="active_radio", value="active", label="Active Mode")
99+
save_radio = Radio(id="save_radio", value="save", label="Save Mode")
100+
101+
exploration_radio_group = RadioGroup(
102+
id="exploration_radio_group",
103+
children=[active_radio, save_radio],
104+
label="Exploration Mode",
105+
)
106+
53107
# Ideas
54108
# 1. Adding radio-button for two modes:
55109
# update mode - reactive to changes to dataset/places/time/variables
@@ -74,7 +128,7 @@ def render_panel(
74128
add_button = Button(id="add_button", text="Add", style={"maxWidth": 100})
75129

76130
controls = Box(
77-
children=[add_button],
131+
children=[exploration_radio_group, add_button],
78132
style={
79133
"display": "flex",
80134
"flexDirection": "row",
@@ -158,14 +212,20 @@ def get_spectra(
158212

159213
variables = list(selected_values.keys())
160214
values = [selected_values[var]["data"] for var in variables]
215+
print("reflectance values::", values)
216+
cleaned_values = [
217+
0 if isinstance(x, float) and math.isnan(x) else x for x in values
218+
]
219+
print("reflectance values after::", cleaned_values)
220+
161221
wavelengths = [
162222
dataset_place[var].attrs.get("wavelength", None) for var in variables
163223
]
164224

165225
res = {
166226
"places": place,
167227
"variable": variables,
168-
"reflectance": values,
228+
"reflectance": cleaned_values,
169229
"wavelength": wavelengths,
170230
}
171231

@@ -197,6 +257,7 @@ def update_text(
197257
Input("@app", "selectedTimeLabel"),
198258
Input("@app", "selectedPlaceGeometry"),
199259
State("@app", "selectedPlaceGroup"),
260+
State("exploration_radio_group", "value"),
200261
Input("add_button", "clicked"),
201262
Input("plot", "chart"),
202263
Output("plot", "chart"),
@@ -208,11 +269,13 @@ def update_plot(
208269
time_label: str | None = None,
209270
place_geo: dict[str, Any] | None = None,
210271
place_group: list[dict[str, Any]] | None = None,
272+
exploration_radio_group: bool | None = None,
211273
_clicked: bool | None = None,
212-
chart=None,
274+
previous_chart: bool | None = None,
213275
) -> tuple[alt.Chart | None, str]:
214-
print("clicked", _clicked)
215-
print("chart", chart)
276+
print("exploration_radio_group", exploration_radio_group)
277+
if exploration_radio_group is None:
278+
return None, "Missing exploration mode choice"
216279
dataset = get_dataset(ctx, dataset_id)
217280
has_point = any(
218281
feature.get("geometry", {}).get("type") == "Point"
@@ -228,7 +291,7 @@ def update_plot(
228291

229292
if label is None:
230293
return None, "There is no label for the selected point"
231-
294+
print("place_geo", place_geo)
232295
if place_geo.get("type") == "Point":
233296
place_group = gpd.GeoDataFrame(
234297
[
@@ -253,30 +316,54 @@ def update_plot(
253316
if source is None:
254317
return None, "No reflectances found in Variables"
255318

256-
chart = (
257-
alt.Chart(source)
258-
.mark_bar(point=True)
259-
.encode(
260-
x="wavelength:Q",
261-
y="reflectance:Q",
262-
color="places:N",
263-
tooltip=["variable", "wavelength", "reflectance"],
264-
)
265-
).properties(width="container", height="container")
319+
if previous_chart is None:
320+
manager.delete_all_data()
321+
322+
if exploration_radio_group == "active":
323+
manager.remove_last_added_place()
324+
manager.add_place_data(source)
325+
chart = (
326+
alt.Chart(manager.all_data)
327+
.mark_bar()
328+
.encode(
329+
x="wavelength:N",
330+
y="reflectance:Q",
331+
xOffset="places:N",
332+
color="places:N",
333+
tooltip=["variable", "wavelength", "reflectance"],
334+
)
335+
).properties(width="container", height="container")
336+
else:
337+
manager.add_place_data(source)
338+
print("in save else case::", manager.all_data["places"].unique())
339+
chart = (
340+
alt.Chart(manager.all_data)
341+
.mark_bar()
342+
.encode(
343+
x="wavelength:N",
344+
y="reflectance:Q",
345+
xOffset="places:N",
346+
color="places:N",
347+
tooltip=["variable", "wavelength", "reflectance"],
348+
)
349+
).properties(width="container", height="container")
350+
print("chart should be ready", chart)
266351

267352
return chart, ""
268353

269354

270355
@panel.callback(
271356
Input("@app", "selectedPlaceGeometry"),
357+
Input("exploration_radio_group", "value"),
272358
Output("add_button", "disabled"),
273359
)
274360
def set_button_disablement(
275361
_ctx: Context,
276362
place_geometry: str | None = None,
363+
exploration_radio_group: str | None = None,
277364
) -> bool:
278365
print("in set_button_disablement", place_geometry)
279-
return not place_geometry
366+
return not place_geometry and exploration_radio_group != "save"
280367

281368

282369
def find_selected_point_label(features_data, target_point):

0 commit comments

Comments
 (0)