import altair as alt
import pandas as pd
import solara
from solara.website.utils import apidoc
# Load the river data
file_path = 'merged_river_data.csv' # Ensure the path is correct on py.cafe
river_data = pd.read_csv(file_path)
# Convert ForecastData from string representation of lists to actual lists
river_data['ForecastData'] = river_data['ForecastData'].apply(eval)
# Convert RiverNumber to string for compatibility
river_data['RiverNumber'] = river_data['RiverNumber'].astype(str)
# Create a map chart using Altair
points = alt.Chart(river_data).mark_circle(
size=10,
color='steelblue',
opacity=0.8
).encode(
longitude='XCoordinate:Q',
latitude='YCoordinate:Q',
tooltip=['RiverNumber', 'Name']
).properties(
width=800,
height=400,
title='Interactive River Flow Forecast Map'
)
@solara.component
def Page():
click_data, set_click_data = solara.use_state({})
hover_data, set_hover_data = solara.use_state({})
def convert_to_dataframe(data):
if data:
relevant_keys = ["RiverNumber", "Name", "XCoordinate", "YCoordinate"]
filtered_data = {key: [data.get(key, '')] for key in relevant_keys}
return pd.DataFrame(filtered_data)
return pd.DataFrame()
def convert_to_forecast_dataframe(data):
if data:
river_number = data.get("RiverNumber", "")
forecast_data = river_data[river_data["RiverNumber"] == river_number]["ForecastData"]
if not forecast_data.empty:
return pd.DataFrame({
"Time": list(range(len(forecast_data.iloc[0]))),
"ForecastData": forecast_data.iloc[0]
})
return pd.DataFrame()
click_df = convert_to_dataframe(click_data)
forecast_df = convert_to_forecast_dataframe(click_data)
with solara.Div() as main:
solara.AltairChart(points, on_click=set_click_data, on_hover=set_hover_data)
solara.Markdown("### Click data:")
if not click_df.empty:
solara.DataFrame(click_df)
else:
solara.Markdown("No data")
solara.Markdown("### Forecast Data:")
if not forecast_df.empty:
base = alt.Chart(forecast_df).encode(
x=alt.X('Time:Q', title='Date'),
y=alt.Y('ForecastData:Q', title='Discharge, cubic meters/sec')
)
area = base.mark_area(color='black').encode(
tooltip=['Time', 'ForecastData']
)
low_flow = base.mark_line(color='green').encode(
y=alt.datum(100) # Assuming low flow threshold is 100 for this example
)
flood_1_5 = base.mark_line(color='magenta').encode(
y=alt.datum(1500) # 1.5 year flood threshold
)
flood_10 = base.mark_rule(color='red', strokeDash=[5, 5]).encode(
y=alt.datum(2000) # 10 year flood threshold
)
flood_25 = base.mark_rule(color='red').encode(
y=alt.datum(2500) # 25 year flood threshold
)
line_plot = (area + low_flow + flood_1_5 + flood_10 + flood_25).properties(
width=600,
height=400,
title=f'Forecast Data for River {click_data.get("RiverNumber", "")}'
)
solara.AltairChart(line_plot)
else:
solara.Markdown("No data")
return main
# This is for documentation purposes
doc = apidoc(solara.AltairChart) # type: ignore