Spaces:
Sleeping
Sleeping
initial commit
Browse files
app.py
ADDED
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import pandas as pd
|
3 |
+
from datetime import datetime
|
4 |
+
import matplotlib.pyplot as plt
|
5 |
+
from pywaffle import Waffle
|
6 |
+
import math
|
7 |
+
|
8 |
+
# Load the life expectancy data from the World Bank
|
9 |
+
# This is a direct link to the CSV data for life expectancy at birth, total (years)
|
10 |
+
file = "/Users/tushar/Documents/tushar_task/life_expectancy_2023_world_back_data.csv"
|
11 |
+
|
12 |
+
# Read the CSV data, skipping the first 4 rows of metadata
|
13 |
+
try:
|
14 |
+
df = pd.read_csv(file)
|
15 |
+
|
16 |
+
life_expectancy_data = df[['Country','Life Expectancy at Birth']].copy()
|
17 |
+
# life_expectancy_data.columns = ['Country', 'Life Expectancy']
|
18 |
+
life_expectancy_data.dropna(inplace=True)
|
19 |
+
countries = sorted(life_expectancy_data['Country'].unique())
|
20 |
+
except Exception as e:
|
21 |
+
print(f"Error loading data: {e}")
|
22 |
+
countries = ["Error loading country data"]
|
23 |
+
life_expectancy_data = pd.DataFrame(columns=['Country', 'Life Expectancy'])
|
24 |
+
|
25 |
+
|
26 |
+
def create_life_calendar(name, birth_year, country):
|
27 |
+
"""
|
28 |
+
Creates a graphical calendar of life, with each year represented
|
29 |
+
as a row of 52 dots (weeks).
|
30 |
+
"""
|
31 |
+
# --- Input Validation and Data Fetching ---
|
32 |
+
if not all([name, birth_year, country]) or country.startswith("Error"):
|
33 |
+
return None, "Please provide your name, birth year, and select a country."
|
34 |
+
|
35 |
+
if life_expectancy_data.empty:
|
36 |
+
return None, "Life expectancy data is unavailable. Cannot generate calendar."
|
37 |
+
|
38 |
+
try:
|
39 |
+
birth_year = int(birth_year)
|
40 |
+
country_data = life_expectancy_data[life_expectancy_data['Country'] == country]
|
41 |
+
if country_data.empty:
|
42 |
+
return None, f"Sorry, life expectancy data for {country} is not available."
|
43 |
+
life_expectancy = int(country_data['Life Expectancy at Birth'].iloc[0])
|
44 |
+
|
45 |
+
except (ValueError, TypeError):
|
46 |
+
return None, "Please enter a valid birth year."
|
47 |
+
|
48 |
+
# --- Calculations ---
|
49 |
+
now = datetime.now()
|
50 |
+
current_year = now.year
|
51 |
+
current_week = now.isocalendar()[1]
|
52 |
+
age = current_year - birth_year
|
53 |
+
|
54 |
+
# --- Plotting Setup ---
|
55 |
+
fig, ax = plt.subplots(figsize=(10, life_expectancy / 10), dpi=120)
|
56 |
+
|
57 |
+
# Define colors
|
58 |
+
past_color = '#d9534f' # Red
|
59 |
+
future_color = '#5cb85c' # Green
|
60 |
+
|
61 |
+
dot_size = 10
|
62 |
+
weeks_in_year = 52
|
63 |
+
|
64 |
+
# --- Main Loop to Plot Dots ---
|
65 |
+
for year in range(1, life_expectancy + 1):
|
66 |
+
for week in range(1, weeks_in_year + 1):
|
67 |
+
# Determine color
|
68 |
+
if year < age:
|
69 |
+
color = past_color
|
70 |
+
elif year == age:
|
71 |
+
color = past_color if week < current_week else future_color
|
72 |
+
else:
|
73 |
+
color = future_color
|
74 |
+
|
75 |
+
# Plot a single dot (week)
|
76 |
+
# We plot from top to bottom, so we reverse the y-coordinate
|
77 |
+
ax.scatter(week, life_expectancy - year, c=color, s=dot_size)
|
78 |
+
|
79 |
+
# --- Formatting and Labels ---
|
80 |
+
# Add year/age labels to the y-axis
|
81 |
+
ax.set_yticks(range(0, life_expectancy, 5))
|
82 |
+
ax.set_yticklabels([str(life_expectancy - i) for i in range(0, life_expectancy, 5)])
|
83 |
+
ax.set_ylabel("Age", fontsize=12)
|
84 |
+
|
85 |
+
# Configure x-axis for weeks
|
86 |
+
ax.set_xticks([1, 13, 26, 39, 52])
|
87 |
+
ax.set_xticklabels(["Week 1", "Week 13", "Week 26", "Week 39", "Week 52"])
|
88 |
+
ax.set_xlabel("Week of the Year", fontsize=12)
|
89 |
+
ax.xaxis.tick_top()
|
90 |
+
ax.xaxis.set_label_position('top')
|
91 |
+
|
92 |
+
# Remove the plot frame/spines for a cleaner look
|
93 |
+
for spine in ['left', 'right', 'bottom']:
|
94 |
+
ax.spines[spine].set_visible(False)
|
95 |
+
|
96 |
+
# Set plot limits
|
97 |
+
ax.set_xlim(0, weeks_in_year + 1)
|
98 |
+
ax.set_ylim(-1, life_expectancy)
|
99 |
+
|
100 |
+
# Create a custom legend
|
101 |
+
legend_elements = [
|
102 |
+
plt.Line2D([0], [0], marker='o', color='w', label='Past Week', markerfacecolor=past_color, markersize=10),
|
103 |
+
plt.Line2D([0], [0], marker='o', color='w', label='Future Week', markerfacecolor=future_color, markersize=10)
|
104 |
+
]
|
105 |
+
ax.legend(handles=legend_elements, loc='center left', bbox_to_anchor=(1.02, 0.5), fontsize=12)
|
106 |
+
|
107 |
+
fig.tight_layout()
|
108 |
+
|
109 |
+
weeks_left = (life_expectancy - age) * 52 - current_week
|
110 |
+
message = f"Hello {name}, based on a life expectancy of {life_expectancy} in {country}, you have approximately {weeks_left:,} weeks remaining."
|
111 |
+
|
112 |
+
return fig, message
|
113 |
+
|
114 |
+
|
115 |
+
# Create the Gradio interface
|
116 |
+
with gr.Blocks(css=".center-text {text-align: center;}",theme=gr.themes.Soft()) as demo:
|
117 |
+
gr.Markdown(
|
118 |
+
"""
|
119 |
+
# Last Sunday
|
120 |
+
Get reminded of how many Sundays remain :)
|
121 |
+
|
122 |
+
This app shows you a visualization of how many Sunday are remaining in your life. It's created to remind oneself that time in life is limited and is not to be wasted.
|
123 |
+
|
124 |
+
It's very easy to use. You simply enter your name and date of birth. Taking life expectancy as 80 years, it tells you how many weeks are left until you die.
|
125 |
+
|
126 |
+
Inspired by the PARAS CHOPRA [Last Sunday](https://chromewebstore.google.com/detail/the-last-sunday-reminder/aiojhapcgfgmiacbbjfgedhlcchmpelh?hl=en) app.
|
127 |
+
"""
|
128 |
+
,elem_classes="center-text"
|
129 |
+
)
|
130 |
+
with gr.Row():
|
131 |
+
name_input = gr.Textbox(label="Your Name")
|
132 |
+
birth_year_input = gr.Number(label="Your Birth Year", minimum=1900, maximum=datetime.now().year)
|
133 |
+
country_input = gr.Dropdown(choices=countries, label="Your Country")
|
134 |
+
|
135 |
+
# output_text = gr.Textbox(label="Your Remaining Sundays")
|
136 |
+
|
137 |
+
# with gr.Row():
|
138 |
+
# expired_input = gr.Number(label="Expired Sundays (Red Dots)", value=1560)
|
139 |
+
# remaining_input = gr.Number(label="Remaining Sundays (Green Dots)", value=2600)
|
140 |
+
|
141 |
+
generate_button = gr.Button("Generate My Life Calendar", variant="primary")
|
142 |
+
|
143 |
+
with gr.Column():
|
144 |
+
output_plot = gr.Plot()
|
145 |
+
output_text = gr.Label()
|
146 |
+
|
147 |
+
generate_button.click(
|
148 |
+
fn=create_life_calendar,
|
149 |
+
inputs=[name_input, birth_year_input, country_input],
|
150 |
+
outputs=[output_plot, output_text]
|
151 |
+
)
|
152 |
+
|
153 |
+
demo.launch()
|
154 |
+
|