Spaces:
Sleeping
Sleeping
| from collections import namedtuple | |
| import altair as alt | |
| import math | |
| import pandas as pd | |
| import streamlit as st | |
| import polars as pl | |
| import openmeteo_requests | |
| from datetime import * | |
| st.set_page_config( | |
| page_title="Weather Data", | |
| page_icon="🌤️", | |
| layout='wide' | |
| ) | |
| st.markdown("# Historic Weather Data for 3 BYU Campuses") | |
| st.markdown("__Explore weather data gathered at all 3 BYU locations from any chosen date range. Observe visuals explaining the temperature, pressure, wind speed, and far more from all locations.__") | |
| columns = st.columns(3, gap='medium') | |
| openmeteo = openmeteo_requests.Client() | |
| st.sidebar.markdown("_Note: Data is only present up to 4 days ago_") | |
| length = st.sidebar.slider("Length of Time Period for Data (Days)", min_value=5, max_value=30, value=15) | |
| campus = ['provo', 'hawaii', 'idaho'] | |
| locations = [(40.2518, 111.6493), (21.6419, 157.9267), (43.8145, 111.7833)] | |
| start_day = st.sidebar.date_input("Start of Period for Data", value=(datetime.today() - timedelta(days=35)), min_value=date(2020, 1, 1), max_value=(datetime.today() - timedelta(days=(length+4)))) | |
| end = (start_day + timedelta(days=length)).strftime('%Y-%m-%d') | |
| start = start_day.strftime('%Y-%m-%d') | |
| zone_select = st.sidebar.selectbox("Choose Timezone", options=['Mountain Time', 'Hawaiian Time']) | |
| zone = 'HST' if zone_select == 'Hawaiian Time' else 'MST' | |
| variables = ['Temperature (F)', 'Apparent Temp (F)', 'Humidity (%)', 'Pressure (hPa)', 'Precipitation (in)', 'Rain (in)', 'Snowfall (in)', 'Cloud Cover (%)', 'Wind Speed (mph)', 'Snow Depth (m)'] | |
| variable_select = st.sidebar.selectbox("Choose variable of interest", options=variables) | |
| variable_dict = { | |
| 'Temperature (F)': 'temperature_2m', | |
| 'Apparent Temp (F)': 'apparent_temperature', | |
| 'Humidity (%)': 'relative_humidity_2m', | |
| 'Pressure (hPa)': 'surface_pressure', | |
| 'Precipitation (in)': 'precipitation', | |
| 'Rain (in)': 'rain', | |
| 'Snowfall (in)': 'snowfall', | |
| 'Cloud Cover (%)': 'cloud_cover', | |
| 'Wind Speed (mph)': 'wind_speed_10m', | |
| 'Snow Depth (m)': 'snow_depth' | |
| } | |
| var = variable_dict[variable_select] | |
| hi_lo = st.sidebar.selectbox("Daily Extremes", options=['Max', 'Min']) | |
| daily_var = 'temperature_2m_max' if hi_lo == 'Max' else 'temperature_2m_min' | |
| def request(url, lat, long, start, end, variable, time_unit, timezone): | |
| params = { | |
| "latitude": lat, | |
| "longitude": long, | |
| "start_date": start, | |
| "end_date": end, | |
| time_unit: variable, | |
| "temperature_unit": "fahrenheit", | |
| 'timezone': timezone, | |
| 'precipitation_unit': 'inch', | |
| 'wind_speed_unit': 'mph' | |
| } | |
| return openmeteo.weather_api(url, params=params)[0] | |
| i = 0 | |
| temp_box = pl.DataFrame() | |
| for location in locations: | |
| actual = request("https://archive-api.open-meteo.com/v1/archive", location[0], location[1], start, end, var, 'hourly', zone) | |
| forecasted = request("https://historical-forecast-api.open-meteo.com/v1/forecast", location[0], location[1], start, end, var, 'hourly', zone) | |
| hourly_actual= actual.Hourly() | |
| hourly_var_actual = hourly_actual.Variables(0).ValuesAsNumpy() | |
| hourly_forecasted = forecasted.Hourly() | |
| hourly_var_forecasted = hourly_forecasted.Variables(0).ValuesAsNumpy() | |
| hourly_data = {"date-time": pd.date_range( | |
| start = pd.to_datetime(hourly_actual.Time(), unit = "s", utc = True), | |
| end = pd.to_datetime(hourly_actual.TimeEnd(), unit = "s", utc = True), | |
| freq = pd.Timedelta(seconds = hourly_actual.Interval()), | |
| inclusive = "left" | |
| )} | |
| hourly_data[var] = hourly_var_actual | |
| hourly_data[f"forecast_{var}"] = hourly_var_forecasted | |
| hourly_dataframe = pl.DataFrame(hourly_data) | |
| hourly_dataframe = hourly_dataframe.with_columns(pl.col('date-time').dt.strftime('%Y-%m-%d').alias('date')) | |
| hourly_dataframe = hourly_dataframe.with_columns(pl.col('date-time').dt.strftime("%H:%M:%S").alias('time')) | |
| with columns[i]: | |
| st.markdown(f"### {campus[i].title()}") | |
| st.dataframe(hourly_dataframe.drop('date-time')) | |
| st.dataframe(hourly_dataframe.select([var, f'forecast_{var}']).describe()[2:9]) | |
| current_campus = hourly_dataframe.with_columns(pl.lit(campus[i]).alias('campus')) | |
| end_month = (datetime.today() - timedelta(days=4)).strftime('%Y-%m-%d') | |
| start_month = (datetime.today() - timedelta(days=35)).strftime('%Y-%m-%d') | |
| daily = request("https://archive-api.open-meteo.com/v1/archive", location[0], location[1], start_month, end_month, daily_var, 'daily', zone).Daily() | |
| daily_data = {"date-time": pd.date_range( | |
| start = pd.to_datetime(daily.Time(), unit = "s", utc = True), | |
| end = pd.to_datetime(daily.TimeEnd(), unit = "s", utc = True), | |
| freq = pd.Timedelta(seconds = daily.Interval()), | |
| inclusive = "left" | |
| )} | |
| daily_data['temperature'] = daily.Variables(0).ValuesAsNumpy() | |
| daily_df = pl.DataFrame(daily_data) | |
| daily_df = daily_df.with_columns(pl.lit(campus[i]).alias('campus')) | |
| if len(temp_box) == 0: | |
| temp_box = pl.DataFrame(current_campus) | |
| temp_line = daily_df | |
| else: | |
| temp_box = temp_box.vstack(current_campus) | |
| temp_line = temp_line.vstack(daily_df) | |
| i+=1 | |
| daily = alt.Chart(temp_line).mark_line().encode( | |
| alt.X("date-time"), | |
| alt.Y('temperature'), | |
| color='campus' | |
| ).properties( | |
| title='Daily Temp Extremes Over Last Month', | |
| width=300, | |
| height=300 | |
| ) | |
| hourly_box = alt.Chart(temp_box).mark_boxplot().encode( | |
| alt.X(var).scale(zero=False), | |
| alt.Y("campus") | |
| ).properties( | |
| title='Hourly Readings', | |
| width=400, | |
| height=300 | |
| ) | |
| grouped = temp_box.select(['time', var, 'campus']).group_by(['time', 'campus']).mean() | |
| hourly_average = alt.Chart(grouped).mark_line().encode( | |
| x="time", | |
| y=var, | |
| color="campus" | |
| ).properties( | |
| title='Average Reading Given Time of Day', | |
| width=400, | |
| height=300 | |
| ) | |
| kpi_max = temp_box.select([var, 'campus']).group_by('campus').max() | |
| pr_hi = kpi_max.filter(pl.col('campus') == 'provo')[var][0] | |
| id_hi = kpi_max.filter(pl.col('campus') == 'idaho')[var][0] | |
| hi_hi = kpi_max.filter(pl.col('campus') == 'hawaii')[var][0] | |
| kpi_low = temp_box.select([var, 'campus']).group_by('campus').min() | |
| pr_lo = kpi_low.filter(pl.col('campus') == 'provo')[var][0] | |
| id_lo = kpi_low.filter(pl.col('campus') == 'idaho')[var][0] | |
| hi_lo = kpi_low.filter(pl.col('campus') == 'hawaii')[var][0] | |
| st.sidebar.altair_chart(daily) | |
| columns[1].altair_chart(hourly_box) | |
| columns[0].altair_chart(hourly_average) | |
| with columns [2]: | |
| sub_cols = st.columns(2) | |
| with sub_cols[0]: | |
| st.markdown(f"Provo Max: {round(pr_hi, 1)}") | |
| st.markdown(f"Hawaii Max: {round(hi_hi, 1)}") | |
| st.markdown(f"Idaho Max: {round(id_hi, 1)}") | |
| with sub_cols[1]: | |
| st.markdown(f"Provo Min: {round(pr_lo, 1)}") | |
| st.markdown(f"Hawaii Min: {round(hi_lo, 1)}") | |
| st.markdown(f"Idaho Min: {round(id_lo, 1)}") |