Climate_Tool / app.py
vibhubathejaTERI's picture
Minor_bug_fixes_line_plots
449b5a7
Raw
History Blame Contribute Delete
38.4 kB
import solara
import pandas as pd
import numpy as np
import xarray as xr
import geopandas as gpd
import asyncio
import plotly.express as px
from scipy.stats import linregress
from constants import (
DEFAULT_DATASET,
DEFAULT_VARIABLE,
DEFAULT_TYPE,
DEFAULT_TIMESCALE,
DEFAULT_MAP_STYLE,
DEFAULT_OPACITY,
DEFAULT_PLOTTED_LINE_COLOR,
DEFAULT_TREND_LINE_COLOR,
DEFAULT_SPATIAL_MEAN_COLOR,
COLOR_SCALES,
MAP_STYLES,
PLOTLY_COLORS,
SHAPEFILE_PATH,
REGION_COLUMN,
)
from Datasets import DATASETS
from utils import (
get_plotly_theme,
load_dataset,
create_heatmap,
create_timeseries_plot,
get_region_bounds,
filter_region_data,
calculate_spatial_mean,
calculate_selected_spatial_mean,
create_selected_timeseries_plot,
get_available_years,
)
tab_index = solara.reactive(0)
right_tab_index = solara.reactive(0)
@solara.component
def Layout(children=[]):
return solara.AppLayout(children=children, sidebar_open=False)
@solara.component
def PlottingControls(show_spatial_mean, set_show_spatial_mean, show_trend_line, set_show_trend_line, show_point_data=None, set_show_point_data=None):
with solara.Row():
solara.Checkbox(
label="Show Spatial Mean",
value=show_spatial_mean,
on_value=set_show_spatial_mean
)
solara.Checkbox(
label="Show Trend Line",
value=show_trend_line,
on_value=set_show_trend_line
)
if show_point_data is not None and set_show_point_data is not None:
solara.Checkbox(
label="Show Point Data",
value=show_point_data,
on_value=set_show_point_data
)
@solara.component
def Page():
dataset_id, set_dataset_id = solara.use_state(DEFAULT_DATASET)
selected_variable, set_selected_variable = solara.use_state(DEFAULT_VARIABLE)
selected_type, set_selected_type = solara.use_state(DEFAULT_TYPE)
selected_timescale, set_selected_timescale = solara.use_state(DEFAULT_TIMESCALE)
selected_scenario, set_selected_scenario = solara.use_state(None) # Reactive state for scenario
data, set_data = solara.use_state(None)
heatmap, set_heatmap = solara.use_state(None)
timeseries, set_timeseries = solara.use_state(None)
selected_timeseries, set_selected_timeseries = solara.use_state(None)
region_timeseries, set_region_timeseries = solara.use_state(None)
value_column, set_value_column = solara.use_state(None)
color_scale, set_color_scale = solara.use_state(None)
map_style, set_map_style = solara.use_state(DEFAULT_MAP_STYLE)
opacity, set_opacity = solara.use_state(DEFAULT_OPACITY)
variables, set_variables = solara.use_state([])
latitude, set_latitude = solara.use_state(0.0)
longitude, set_longitude = solara.use_state(0.0)
use_regions, set_use_regions = solara.use_state(False)
region, set_region = solara.use_state("India")
regions, set_regions = solara.use_state(["India"])
geodataframe, set_geodataframe = solara.use_state(None)
region_bounds, set_region_bounds = solara.use_state(None)
show_spatial_mean, set_show_spatial_mean = solara.use_state(True)
show_region_spatial_mean, set_show_region_spatial_mean = solara.use_state(True)
show_region_trend_line, set_show_region_trend_line = solara.use_state(True)
show_selected_trend_line, set_show_selected_trend_line = solara.use_state(True)
spatial_mean_data, set_spatial_mean_data = solara.use_state({"overall_mean": None, "timeseries": pd.DataFrame()})
selected_spatial_mean_data, set_selected_spatial_mean_data = solara.use_state({"overall_mean": None, "timeseries": pd.DataFrame()})
available_years, set_available_years = solara.use_state([])
from_year, set_from_year = solara.use_state(None)
to_year, set_to_year = solara.use_state(None)
use_timeframe, set_use_timeframe = solara.use_state(False)
selected_coords, set_selected_coords = solara.use_state([])
show_stats_for_nerds, set_show_stats_for_nerds = solara.use_state(False)
loading_data, set_loading_data = solara.use_state(False)
loading_spatial_mean, set_loading_spatial_mean = solara.use_state(False)
show_trend_line, set_show_trend_line = solara.use_state(True)
plotted_line_color, set_plotted_line_color = solara.use_state(DEFAULT_PLOTTED_LINE_COLOR)
trend_line_color, set_trend_line_color = solara.use_state(DEFAULT_TREND_LINE_COLOR)
spatial_mean_color, set_spatial_mean_color = solara.use_state(DEFAULT_SPATIAL_MEAN_COLOR)
def get_available_types():
return sorted(set(d["type"] for d in DATASETS if d["variable"] == selected_variable))
def get_available_timescales():
return sorted(set(d["timescale"] for d in DATASETS if d["variable"] == selected_variable and d["type"] == selected_type))
def get_available_scenarios():
scenarios = sorted(set(d["scenario"] for d in DATASETS if d["variable"] == selected_variable and d["type"] == selected_type and d["timescale"] == selected_timescale and "scenario" in d))
return scenarios if scenarios else []
def update_dataset_id():
matching_datasets = [
d["id"] for d in DATASETS
if d["variable"] == selected_variable
and d["type"] == selected_type
and d["timescale"] == selected_timescale
and (d.get("scenario") == selected_scenario if selected_type == "Projected" else True)
]
if matching_datasets:
set_dataset_id(matching_datasets[0])
else:
set_dataset_id(None)
set_loading_data(False)
solara.Info("No dataset available for the selected combination.")
def reset_scenario():
available_scenarios = get_available_scenarios()
if selected_type != "Projected":
set_selected_scenario(None)
elif available_scenarios:
set_selected_scenario(available_scenarios[0])
else:
set_selected_scenario(None)
solara.use_effect(update_dataset_id, dependencies=[selected_variable, selected_type, selected_timescale, selected_scenario])
solara.use_effect(reset_scenario, dependencies=[selected_type, selected_variable, selected_timescale])
def load_shapefile():
try:
gdf = gpd.read_file(SHAPEFILE_PATH)
set_regions(["India"] + sorted(gdf[REGION_COLUMN].unique().tolist()))
set_geodataframe(gdf)
except Exception as e:
print(f"Error loading shapefile: {e}")
solara.use_effect(load_shapefile, dependencies=[])
def update_region_bounds():
if geodataframe is not None and region != "India" and use_regions:
try:
set_region_bounds(get_region_bounds(geodataframe, region))
set_loading_spatial_mean(True)
set_spatial_mean_data({"overall_mean": None, "timeseries": pd.DataFrame()})
except Exception as e:
print(f"Error getting region bounds: {e}")
set_region_bounds(None)
set_spatial_mean_data({"overall_mean": None, "timeseries": pd.DataFrame()})
set_loading_spatial_mean(False)
else:
set_region_bounds(None)
set_spatial_mean_data({"overall_mean": None, "timeseries": pd.DataFrame()})
set_loading_spatial_mean(False)
solara.use_effect(update_region_bounds, dependencies=[region, use_regions, geodataframe])
def load_available_years():
if dataset_id:
dataset = next(d for d in DATASETS if d["id"] == dataset_id)
years = get_available_years(dataset)
set_available_years(years)
if years:
set_from_year(years[0])
set_to_year(years[-1])
else:
set_from_year(None)
set_to_year(None)
solara.use_effect(load_available_years, dependencies=[dataset_id])
async def async_compute_spatial_mean():
if not show_region_spatial_mean:
set_spatial_mean_data({"overall_mean": None, "timeseries": pd.DataFrame()})
set_loading_spatial_mean(False)
return
await asyncio.sleep(0.1)
if dataset_id:
dataset = next(d for d in DATASETS if d["id"] == dataset_id)
mean_data = calculate_spatial_mean(dataset, geodataframe, region, from_year, to_year, use_timeframe)
set_spatial_mean_data(mean_data)
set_loading_spatial_mean(False)
def compute_spatial_mean():
asyncio.create_task(async_compute_spatial_mean())
solara.use_effect(compute_spatial_mean,
dependencies=[dataset_id, region, use_regions, geodataframe,
show_region_spatial_mean, from_year, to_year, use_timeframe])
def compute_region_timeseries():
if not show_region_spatial_mean or not dataset_id:
set_region_timeseries(None)
return
dataset = next(d for d in DATASETS if d["id"] == dataset_id)
if spatial_mean_data["timeseries"].empty:
set_region_timeseries(None)
return
try:
dataset_nc = xr.open_dataset(dataset["timeseries_path"], decode_timedelta=False)
variable = list(dataset_nc.data_vars)[0]
dataset_nc.close()
except Exception as e:
print(f"Error accessing dataset variable: {e}")
set_region_timeseries(None)
return
if variable not in spatial_mean_data["timeseries"].columns:
print(f"Variable {variable} not found in spatial mean data. Recomputing spatial mean.")
set_region_timeseries(None)
return
fig = px.line(
spatial_mean_data["timeseries"],
x="year",
y=variable,
title=f"Spatial Mean {dataset['name']} for {region}, {from_year}-{to_year}" if use_timeframe else f"Spatial Mean {dataset['name']} for {region}",
labels={"year": "Year", variable: dataset["name"]},
color_discrete_sequence=[plotted_line_color]
)
fig.data[0].name = f"{region} Spatial Mean"
if show_region_trend_line and len(spatial_mean_data["timeseries"]) > 2:
x_series = spatial_mean_data["timeseries"]["year"]
y_series = spatial_mean_data["timeseries"][variable]
valid_indices = y_series.notna()
x_valid = x_series[valid_indices].values
y_valid = y_series[valid_indices].values
if len(x_valid) > 2:
y_numeric = y_valid
if pd.api.types.is_timedelta64_dtype(y_numeric.dtype):
y_numeric = y_numeric / np.timedelta64(1, 'D')
x_norm = x_valid - x_valid.mean()
coeffs = np.polyfit(x_norm, y_numeric, deg=2)
poly = np.poly1d(coeffs)
trend_line = poly(x_norm)
midpoint_idx = len(x_valid) // 2
slope = 2 * coeffs[0] * x_norm[midpoint_idx] + coeffs[1]
_, _, r_value, p_value, _ = linregress(x_valid, y_numeric)
trend = "Increasing" if p_value < 0.05 and slope > 0 else "Decreasing" if p_value < 0.05 and slope < 0 else "No Significant Trend"
fig.add_scatter(
x=x_valid,
y=trend_line,
mode="lines",
name=f"{region} Trend",
line=dict(color=trend_line_color, dash="dash")
)
fig.add_annotation(
x=x_valid.max(),
y=y_valid.min(),
text=f"Slope: {slope:.4f}<br>p-value: {p_value:.4f}<br>Trend: {trend}",
showarrow=False,
xanchor="right",
yanchor="top",
bgcolor="white" if not solara.lab.theme.dark_effective else "#333333",
bordercolor="black",
borderpad=4,
opacity=0.8,
font=dict(size=12, color="black" if not solara.lab.theme.dark_effective else "white")
)
fig.update_layout(
xaxis_title="Year",
yaxis_title=dataset["name"],
height=550,
width=650,
showlegend=True,
legend=dict(
x=0.99,
y=0.99,
xanchor="right",
yanchor="top",
bgcolor="rgba(0, 0, 0, 0)"
),
template=get_plotly_theme()
)
set_region_timeseries(fig)
solara.use_effect(compute_region_timeseries,
dependencies=[dataset_id, region, use_regions, spatial_mean_data,
show_region_trend_line, plotted_line_color, trend_line_color,
from_year, to_year, use_timeframe, selected_variable])
def compute_selected_spatial_mean():
if not selected_coords:
set_selected_spatial_mean_data({"overall_mean": None, "timeseries": pd.DataFrame()})
set_selected_timeseries(None)
return
if dataset_id:
dataset = next(d for d in DATASETS if d["id"] == dataset_id)
mean_data = calculate_selected_spatial_mean(dataset, selected_coords, from_year, to_year, use_timeframe)
set_selected_spatial_mean_data(mean_data)
set_selected_timeseries(create_selected_timeseries_plot(
dataset["timeseries_path"],
dataset["name"],
selected_coords,
plotted_line_color,
mean_data,
from_year,
to_year,
use_timeframe,
show_selected_trend_line,
trend_line_color,
spatial_mean_color
))
solara.use_effect(compute_selected_spatial_mean,
dependencies=[dataset_id, selected_coords, from_year, to_year, use_timeframe,
plotted_line_color, show_selected_trend_line, trend_line_color, spatial_mean_color])
def handle_map_click(click_data):
if click_data and "points" in click_data and "point_indexes" in click_data["points"]:
idx = click_data["points"]["point_indexes"][0]
row = data.iloc[idx]
set_latitude(float(row["lat"]))
set_longitude(float(row["lon"]))
def handle_map_selection(selection_data):
if selection_data and "points" in selection_data and "point_indexes" in selection_data["points"]:
selected_indices = selection_data["points"]["point_indexes"]
coords = [(float(data.iloc[idx]["lat"]), float(data.iloc[idx]["lon"])) for idx in selected_indices]
set_selected_coords(coords)
else:
set_selected_coords([])
def generate_timeseries():
if dataset_id and latitude and longitude:
dataset = next(d for d in DATASETS if d["id"] == dataset_id)
set_timeseries(create_timeseries_plot(
dataset["timeseries_path"],
dataset["name"],
latitude,
longitude,
plotted_line_color,
spatial_mean_data=spatial_mean_data,
show_spatial_mean=show_spatial_mean,
from_year=from_year,
to_year=to_year,
use_timeframe=use_timeframe,
region=region,
show_trend_line=show_trend_line,
trend_line_color=trend_line_color,
spatial_mean_color=spatial_mean_color
))
solara.use_effect(generate_timeseries, [
dataset_id, latitude, longitude, plotted_line_color, spatial_mean_data,
show_spatial_mean, from_year, to_year, use_timeframe, region,
show_trend_line, trend_line_color, spatial_mean_color
])
async def async_load_and_visualize():
set_loading_data(True)
if dataset_id:
dataset = next(d for d in DATASETS if d["id"] == dataset_id)
print(f"Loading dataset: {dataset['id']} - {dataset['name']}")
loaded_data, float_vars, grid_size = load_dataset(dataset)
set_variables([var for var in float_vars if var not in ["lat", "lon", "latitude", "longitude"]])
new_value_column = float_vars[0] if float_vars else None
set_value_column(new_value_column)
if use_regions and geodataframe is not None:
loaded_data = filter_region_data(loaded_data, geodataframe, region)
if not new_value_column:
set_loading_data(False)
return
filtered_data = loaded_data[loaded_data[new_value_column].notnull()][["lat", "lon", new_value_column]]
set_heatmap(create_heatmap(filtered_data, dataset["name"], new_value_column,
grid_size, color_scale, map_style, opacity))
set_data(filtered_data)
set_selected_coords([])
set_loading_data(False)
def load_and_visualize():
asyncio.create_task(async_load_and_visualize())
solara.use_effect(load_and_visualize,
dependencies=[dataset_id, color_scale, map_style,
opacity, region, use_regions])
def update_color_scale():
if dataset_id:
dataset = next(d for d in DATASETS if d["id"] == dataset_id)
set_color_scale(dataset["color_scale"])
solara.use_effect(update_color_scale, dependencies=[dataset_id])
def sync_map_style_with_theme():
if map_style not in ["carto-darkmatter", "carto-positron"]:
return
new_map_style = "carto-darkmatter" if solara.lab.theme.dark_effective else "carto-positron"
set_map_style(new_map_style)
solara.use_effect(sync_map_style_with_theme, dependencies=[solara.lab.theme.dark_effective])
with solara.AppLayout(sidebar_open=True):
with solara.AppBar():
solara.Image("data/logo/TERI Logo Seal.png", width="80px", classes=["mx-2"])
solara.AppBarTitle("TERI Climate Tools - Climate Data Explorer")
solara.lab.ThemeToggle()
with solara.Sidebar():
with solara.Card("Controls", margin=0, elevation=0):
with solara.Column():
solara.Details(
summary="Dataset Settings",
children=[
solara.Select(
label="Variable",
value=selected_variable,
values=["Tmin", "Tmax", "Precipitation", "Climate Extremes"],
dense=True,
on_value=lambda value: [set_selected_variable(value), set_loading_data(True)]
),
solara.Select(
label="Dataset Type",
value=selected_type,
values=get_available_types(),
dense=True,
on_value=lambda value: [set_selected_type(value), set_loading_data(True)],
disabled=not selected_variable
),
solara.Select(
label="Time Scale",
value=selected_timescale,
values=get_available_timescales(),
dense=True,
on_value=lambda value: [set_selected_timescale(value), set_loading_data(True)],
disabled=not selected_variable or not selected_type
),
solara.Select(
label="Scenario",
value=selected_scenario,
values=get_available_scenarios(),
dense=True,
on_value=lambda value: [set_selected_scenario(value), set_loading_data(True)],
disabled=not get_available_scenarios()
) if selected_type == "Projected" else solara.Markdown("**No scenarios available**" if selected_type == "Projected" else ""),
solara.Select(
label="Value",
value=value_column,
values=variables,
on_value=set_value_column,
disabled=not variables
)
],
expand=False
)
solara.Details(
summary="Visualization Settings",
children=[
solara.Select(
label="Color Scale",
value=color_scale,
values=COLOR_SCALES,
on_value=lambda value: [set_color_scale(value), set_loading_data(True)]
),
solara.Select(
label="Map Style",
value=map_style,
values=MAP_STYLES,
on_value=lambda value: [set_map_style(value), set_loading_data(True)]
),
solara.SliderFloat(
label="Opacity",
value=opacity,
min=0.1, max=1.0, step=0.1,
on_value=lambda value: [set_opacity(value), set_loading_data(True)]
),
solara.Details(
summary="Line Plot Settings",
children=[
solara.Select(
label="Plotted Line Color",
value=plotted_line_color,
values=PLOTLY_COLORS,
on_value=set_plotted_line_color
),
solara.Select(
label="Trend Line Color",
value=trend_line_color,
values=PLOTLY_COLORS,
on_value=set_trend_line_color
),
solara.Select(
label="Spatial Mean Color",
value=spatial_mean_color,
values=PLOTLY_COLORS,
on_value=set_spatial_mean_color
)
],
expand=False
)
],
expand=False
)
solara.Details(
summary="Time Series Settings",
children=[
solara.Checkbox(
label="Use Specific Time Frame",
value=use_timeframe,
on_value=set_use_timeframe
),
solara.Select(
label="From Year",
value=from_year,
values=available_years,
on_value=set_from_year,
disabled=not available_years or not use_timeframe
),
solara.Select(
label="To Year",
value=to_year,
values=[y for y in available_years if y >= (from_year or available_years[0])],
on_value=set_to_year,
disabled=not available_years or not use_timeframe
)
],
expand=False
)
with solara.VBox(classes=["h-full", "w-full"]):
if loading_data:
solara.SpinnerSolara(size="100px")
elif heatmap:
with solara.Columns(widths=[2, 1], gutters=True, gutters_dense=True):
with solara.Column():
solara.FigurePlotly(heatmap, on_click=handle_map_click, on_selection=handle_map_selection)
with solara.Column():
with solara.lab.Tabs(value=right_tab_index):
with solara.lab.Tab("Point Based Analysis"):
solara.Details(
summary="Coordinates",
children=[
solara.InputFloat(label="Latitude", value=latitude, on_value=set_latitude),
solara.InputFloat(label="Longitude", value=longitude, on_value=set_longitude),
solara.Button(label="Generate Plot", color="primary",
text=True, on_click=generate_timeseries)
],
expand=False
)
if timeseries:
solara.FigurePlotly(timeseries)
if dataset_id:
dataset = next(d for d in DATASETS if d["id"] == dataset_id)
variable = list(xr.open_dataset(dataset["timeseries_path"], decode_timedelta=False).data_vars)[0]
dataset_xr = xr.open_dataset(dataset["timeseries_path"], decode_timedelta=False)
lat_idx = np.abs((dataset_xr.get("lat", dataset_xr.get("latitude")).values - latitude)).argmin()
lon_idx = np.abs((dataset_xr.get("lon", dataset_xr.get("longitude")).values - longitude)).argmin()
timeseries_data = dataset_xr[variable].isel(lat=lat_idx, lon=lon_idx).to_dataframe().reset_index()
dataset_xr.close()
if use_timeframe and from_year is not None and to_year is not None:
timeseries_data = timeseries_data[(timeseries_data["year"] >= from_year) & (timeseries_data["year"] <= to_year)]
timeseries_data = timeseries_data[["year", variable]].rename(columns={variable: dataset["name"]})
show_timeseries_data, set_show_timeseries_data = solara.use_state(False)
PlottingControls(show_spatial_mean, set_show_spatial_mean, show_trend_line, set_show_trend_line, show_timeseries_data, set_show_timeseries_data)
if show_timeseries_data:
solara.Markdown("### Point Data")
display_df = timeseries_data.copy()
if pd.api.types.is_numeric_dtype(display_df[dataset["name"]]):
display_df[dataset["name"]] = display_df[dataset["name"]].map('{:.2f}'.format)
solara.DataFrame(display_df, items_per_page=10)
csv_data = timeseries_data.to_csv(index=False)
solara.FileDownload(
data=csv_data,
filename=f"timeseries_lat_{latitude:.2f}_lon_{longitude:.2f}.csv",
label="Download Point Data as CSV"
)
else:
solara.Info(label="Click a map point to generate a plot.")
with solara.lab.Tab("Region Based Analysis"):
solara.Details(
summary="State Based Analysis",
children=[
child for child in [
solara.Select(
label="Region",
value=region,
values=regions,
on_value=lambda value: [set_region(value), set_use_regions(value != "India"), set_loading_data(True), set_loading_spatial_mean(True)]
),
solara.Row(children=[
solara.Checkbox(
label="Show Region Spatial Mean",
value=show_region_spatial_mean,
on_value=set_show_region_spatial_mean
),
solara.Checkbox(
label="Show Trend Line",
value=show_region_trend_line,
on_value=set_show_region_trend_line
)
]),
solara.Markdown("### Spatial Mean Value") if show_region_spatial_mean else None,
solara.SpinnerSolara(size="64px") if show_region_spatial_mean and loading_spatial_mean else None,
solara.Markdown(
f"**Spatial Mean for {region} ({from_year}-{to_year}):** {spatial_mean_data['overall_mean'].days:.2f} days"
if use_timeframe and from_year and to_year
else f"**Spatial Mean for {region} (All Years):** {spatial_mean_data['overall_mean'].days:.2f} days"
) if show_region_spatial_mean and isinstance(spatial_mean_data['overall_mean'], pd.Timedelta) and not loading_spatial_mean else solara.Markdown(
f"**Spatial Mean for {region} ({from_year}-{to_year}):** {spatial_mean_data['overall_mean']:.2f}"
if use_timeframe and from_year and to_year
else f"**Spatial Mean for {region} (All Years):** {spatial_mean_data['overall_mean']:.2f}"
) if show_region_spatial_mean and spatial_mean_data['overall_mean'] is not None and not loading_spatial_mean else None,
solara.Markdown("**Spatial Mean calculation not available**") if show_region_spatial_mean and not loading_spatial_mean and spatial_mean_data['overall_mean'] is None else None,
solara.Markdown("### Region Spatial Mean Timeseries") if show_region_spatial_mean else None,
solara.FigurePlotly(region_timeseries) if show_region_spatial_mean and region_timeseries else None,
solara.Info("Please wait we are calculating the Spatial Mean and Plotting the Plots") if show_region_spatial_mean and not region_timeseries else None
] if child is not None
],
expand=False
)
if selected_coords:
solara.Markdown(
f"**Spatial Mean of Selected Points{' (' + str(from_year) + '-' + str(to_year) + ')' if use_timeframe and from_year and to_year else ''}:** {selected_spatial_mean_data['overall_mean']:.2f}"
if selected_spatial_mean_data["overall_mean"] is not None
else "**No spatial mean available**"
)
if selected_timeseries:
solara.FigurePlotly(selected_timeseries)
selected_data = selected_spatial_mean_data.get("timeseries", pd.DataFrame())
if not selected_data.empty:
if dataset_id:
dataset = next(d for d in DATASETS if d["id"] == dataset_id)
selected_data_display = selected_data[["year", list(xr.open_dataset(dataset["timeseries_path"], decode_timedelta=False).data_vars)[0]]]
selected_data_display = selected_data_display.rename(columns={list(xr.open_dataset(dataset["timeseries_path"], decode_timedelta=False).data_vars)[0]: dataset["name"]})
show_selected_data, set_show_selected_data = solara.use_state(False)
with solara.Row():
solara.Checkbox(
label="Show Trend Line",
value=show_selected_trend_line,
on_value=set_show_selected_trend_line
)
solara.Checkbox(
label="Show Region Data",
value=show_selected_data,
on_value=set_show_selected_data
)
solara.Checkbox(
label="Stats for Nerds",
value=show_stats_for_nerds,
on_value=set_show_stats_for_nerds
)
if show_selected_data:
solara.Markdown("### Region Data")
display_df = selected_data_display.copy()
if pd.api.types.is_numeric_dtype(display_df[dataset["name"]]):
display_df[dataset["name"]] = display_df[dataset["name"]].map('{:.2f}'.format)
solara.DataFrame(display_df, items_per_page=10)
csv_data = selected_data_display.to_csv(index=False)
solara.FileDownload(
data=csv_data,
filename="selected_points_spatial_mean.csv",
label="Download Region Data as CSV"
)
else:
solara.Info(label="No data available for selected region.")
else:
solara.Info("Select points on the heatmap to generate a region.")
if show_stats_for_nerds and selected_coords:
coords_df = pd.DataFrame(selected_coords, columns=["Latitude", "Longitude"])
solara.Markdown(f"**Total Points Selected**: {len(selected_coords)}")
solara.DataFrame(coords_df, items_per_page=5)
coords_csv_data = coords_df.to_csv(index=False)
solara.FileDownload(
data=coords_csv_data,
filename="selected_coordinates.csv",
label="Download Selected Coordinates as CSV"
)
elif show_stats_for_nerds:
solara.Info("Select points to view coordinates.")
else:
solara.Info(label="Select points on the heatmap to view spatial mean and time series.")