import openmeteo_requests import requests_cache import polars as pl from retry_requests import retry import streamlit as st from datetime import datetime, timedelta import pytz from lets_plot import * from streamlit_letsplot import st_letsplot import numpy as np #API Fetch openmeteo = openmeteo_requests.Client() #Empty Frames locations = [ {"name": "Rexburg, Idaho", "latitude": 43.8251, "longitude": -111.7924}, {"name": "Provo, Utah", "latitude": 40.2338, "longitude": -111.6585}, {"name": "Laie, Hawaii", "latitude": 21.6210, "longitude": -157.9753} ] location_names = [location["name"] for location in locations] filtered_forecasts = {} filtered_histories = {} historical_data = [] forecast_data = [] timezones = pytz.all_timezones def find_max(df): daily_highs = df.group_by(by = 'Date').agg(pl.max("Temperature").alias('max')) return daily_highs, df # Date Variables today = datetime.today() default = today - timedelta(days=14) # Streamlit Variables start_date = st.sidebar.date_input( 'Select start date:', value = default, max_value= default ) selected_timezone = st.sidebar.selectbox( 'Choose a timezone:', timezones ) end_date = start_date + timedelta(days=14) temperature_option = st.sidebar.selectbox( 'Select Temperature Type', ('Highest', 'Lowest') ) city_option = st.sidebar.selectbox( 'Select City', ('Rexburg, Idaho', 'Provo, Utah', 'Laie, Hawaii') ) # Display the selected date range st.sidebar.write(f"Date Range: {start_date} to {end_date}") # Get Forecast Data for location in locations: url = "https://api.open-meteo.com/v1/forecast" params = { "latitude": location["latitude"], "longitude": location["longitude"], "start_date": start_date.strftime('%Y-%m-%d'), "end_date": end_date.strftime('%Y-%m-%d'), "hourly": "temperature_2m" } # Fetch weather data responses = openmeteo.weather_api(url, params=params) response = responses[0] hourly = response.Hourly() hourly_temperature_2m = hourly.Variables(0).ValuesAsNumpy() # Convert timestamp to datetime start = datetime.fromtimestamp(hourly.Time()) end = datetime.fromtimestamp(hourly.TimeEnd()) freq = timedelta(seconds=hourly.Interval()) # Create Polars DataFrame hourly_data = pl.select( date = pl.datetime_range(start, end, freq, closed = "left"), temperature_2m = hourly_temperature_2m, location = [location["name"]]) hourly_dataframe = pl.DataFrame(data = hourly_data) historical_data.append(hourly_dataframe) # Concatenate all DataFrames combined_historical = pl.DataFrame(pl.concat(historical_data)).explode('location') # Get True Historical Data for location in locations: url = "https://archive-api.open-meteo.com/v1/archive" params = { "latitude": location["latitude"], "longitude": location["longitude"], "start_date": start_date.strftime('%Y-%m-%d'), "end_date": end_date.strftime('%Y-%m-%d'), "hourly": "temperature_2m" } # Fetch weather data responses = openmeteo.weather_api(url, params=params) response = responses[0] hourly = response.Hourly() hourly_temperature_2m = hourly.Variables(0).ValuesAsNumpy() # Convert timestamp to datetime start = datetime.fromtimestamp(hourly.Time()) end = datetime.fromtimestamp(hourly.TimeEnd()) freq = timedelta(seconds=hourly.Interval()) # Create Polars DataFrame hourly_data = pl.select( date = pl.datetime_range(start, end, freq, closed = "left"), temperature_2m = hourly_temperature_2m, location = [location["name"]]) hourly_dataframe = pl.DataFrame(data = hourly_data) forecast_data.append(hourly_dataframe) combined_forecast = pl.DataFrame(pl.concat(forecast_data)).explode('location') for name in location_names: filtered_forecasts[name] = (combined_forecast.filter(pl.col("location") == name).drop('location').rename({'date': 'Date'}).rename({'temperature_2m': 'Temperature'}).with_columns(pl.col('Temperature') * 9/5 + 32)) filtered_histories[name] = (combined_historical.filter(pl.col("location") == name).drop('location').rename({'date': 'Date'}).rename({'temperature_2m': 'Temperature'}).with_columns(pl.col('Temperature') * 9/5 + 32)) tab1, tab2, tab3 = st.tabs(["Data", "Visualisations", "KPIs"]) with tab1: st.title("Forecasted Weather vs Actual Weather by City") st.header('Forecasts') st.markdown("