standard app name

This commit is contained in:
2025-01-02 01:16:42 -05:00
parent b7850faa13
commit 7db0b08080

214
app.py Normal file
View File

@ -0,0 +1,214 @@
import pandas as pd
import vobject
import requests
from datetime import datetime, date
import matplotlib.pyplot as plt
import calmap
import streamlit as st
import plotly.express as px
import plotly.graph_objects as go
import json
import os
# Function to load data from a JSON file
def load_data(file_path):
try:
with open(file_path, 'r') as file:
if os.path.getsize(file_path) == 0: return {}
return json.load(file)
except FileNotFoundError:
print("settings file not found")
return {}
except :
print("settings file invalid")
return {}
# Function to save data to a JSON file
def save_data(file_path, data):
with open(file_path, 'w') as file:
json.dump(data, file)
# Function to create a calendar heatmap for a specific year
def create_calendar_heatmap(event_series, year):
# Filter the series to include only the specific year
event_series_year = event_series[event_series.index.year == year]
# Create a complete date range for the year
all_dates_year = pd.date_range(start=f'{year}-01-01', end=f'{year}-12-31')
# Reindex the Series to include all dates in the year and fill missing dates with zero
event_series_year = event_series_year.reindex(all_dates_year, fill_value=0)
# Create a DataFrame for Plotly
df_year = pd.DataFrame({'Date': event_series_year.index, 'Events': event_series_year.values})
# Generate day of the week and week of the year
df_year['DayOfWeek'] = df_year['Date'].dt.dayofweek
df_year['WeekOfYear'] = df_year['Date'].dt.isocalendar().week
df_year['Month'] = df_year['Date'].dt.strftime('%b')
# Create the Plotly figure
fig = go.Figure(data=go.Heatmap(
z=df_year['Events'],
x=df_year['WeekOfYear'],
y=df_year['DayOfWeek'],
colorscale='YlGn',
showscale=True,
colorbar=dict(
title='# of Events',
orientation='h', # Set the color scale to horizontal
len=0.3, # Adjust the length of the color scale
thickness=10,
x=0.98,
y=1,
xanchor="right",
yanchor="bottom", # Position the color scale at the bottom
),
hoverinfo='z+x+y'
))
# Set the aspect ratio to ensure square boxes
fig.update_yaxes(scaleanchor="x", scaleratio=1, constrain="domain")
# Update the layout with the axes
fig.update_layout(
title=f'Calendar Heatmap for {year}',
yaxis=dict(
tickmode='array',
tickvals=[0, 1, 2, 3, 4, 5, 6],
ticktext=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
range=[-1.2, 6.5], # Adjust the range to eliminate space
automargin=True, # Adjust margins automatically
domain=[0.1,0.95] # Use available space effectively
),
xaxis=dict(
tickmode='array',
tickvals=list(range(1, 54)),
ticktext=list(range(1, 54)),
title=dict(
text='Weeks of the Year',
standoff=0
),
title_standoff=0, # Adjust the distance of the title from the axis
tickangle=-90, # Adjust the angle of the week numbers
ticklen=2,
side='top', # Display x-axis ticks above the heatmap
automargin=True, # Adjust margins automatically
),
autosize=True,
margin=dict(
l=50,
r=50,
b=30, # Increase bottom margin to fit month names
t=30, # Increase top margin to fit week numbers
pad=0
),
height=450, # Fixed height to avoid excessive space
)
# Add month annotations with arrows at the bottom
month_starts = df_year.iloc[:-10].groupby('Month')['WeekOfYear'].min().to_dict()
for month, week in month_starts.items():
fig.add_annotation(
x=week,
y=-0.5, # Position below the x-axis
text=month,
showarrow=False,
arrowhead=2,
ax=week,
ay=0, # Position the arrow closer
xref="x",
yref="y",
#font=dict(size=12, color="black"),
xanchor='left',
yanchor='top'
)
return fig
def save_load():
st.session_state['options'].pop("New")
save_data(settings_file, st.session_state['options'])
st.session_state['options'] = load_data(settings_file)
def update_params():
st.session_state['cal_url'] = st.session_state['options'][st.session_state['setup']]['cal_url']
st.session_state['number_of_years'] = st.session_state['options'][st.session_state['setup']]['number_of_years']
# set webpage title
st.title("Yearly Activity Heatmaps")
# File path for data storage
settings_file = 'settings.json'
# Load persisted data if it exists; set default values otherwise
st.session_state['options'] = load_data(settings_file)
st.session_state['options']["New"] = {
'cal_url':"https://canada-holidays.ca/ics?cd=true",
'number_of_years': 3
}
# Get the Calendar Export link and number of years from sidebar menu
st.sidebar.header("Settings")
st.session_state['setup'] = st.sidebar.selectbox("Choose a Setup:", st.session_state['options'].keys())
st.session_state['cal_url'] = st.sidebar.text_input("Enter The Calendar Export Link:", value=st.session_state['options'][st.session_state['setup']]['cal_url'])
st.session_state['number_of_years'] = st.sidebar.number_input("Enter the number of years:", min_value=1, max_value=10, value=st.session_state['options'][st.session_state['setup']]['number_of_years'])
update_params()
if(st.session_state['setup'] == "New"):
setup_save_name = st.sidebar.text_input("Setup Save Name:", value='yahoo')
st.session_state['options'][setup_save_name] = {
'cal_url': st.session_state['cal_url'],
'number_of_years': st.session_state['number_of_years']
}
st.sidebar.button("Save",on_click=save_load)
response = requests.get(st.session_state['cal_url'])
if response.status_code == 200:
# Parse the .ics file
cal = vobject.readOne(response.text)
else:
print("Failed to download the file")
# Create a dictionary to store event counts by date
event_counts = {}
for component in cal.components():
if component.name == "VEVENT":
event_date = component.dtstart.value
if isinstance(event_date, datetime):
event_date = event_date.date()
if event_date in event_counts:
event_counts[event_date] += 1
else:
event_counts[event_date] = 1
# Convert the dictionary to a pandas Series
event_series = pd.Series(event_counts)
# Ensure the index is in datetime format
event_series.index = pd.to_datetime(event_series.index)
# Get the current year
current_year = datetime.now().year
# Create a list of years to plot
years_to_plot = [current_year - i for i in range(st.session_state['number_of_years'])]
# Plot each year's data
for year in years_to_plot:
fig = create_calendar_heatmap(event_series, year)
st.plotly_chart(fig)