Files
dotfiles/scripts/sleep-tracker.py
2025-06-05 00:38:09 +03:00

97 lines
3.3 KiB
Python
Executable File

#!/usr/bin/env python
import matplotlib.pyplot as plt
import pandas as pd
import argparse
from datetime import datetime
# Hardcoded file path
FILE_PATH = "/home/kyren/personal/grimoire/sleep-tracker.md"
def parse_time(value, is_evening=False):
if value == "N/A" or value == "Morning" or value == "Evening":
return None
time = datetime.strptime(value, "%I:%M %p")
hour = time.hour + time.minute / 60
if is_evening and time.hour < 12:
hour += 24
return hour
def format_time(value):
if pd.isna(value):
return "N/A"
hour = int(value) % 24
minute = int((value - int(value)) * 60)
period = "AM" if hour < 12 else "PM"
hour = hour if hour <= 12 else hour - 12
hour = 12 if hour == 0 else hour
return f"{hour}:{minute:02d} {period}"
def read_data(file_path):
with open(file_path, 'r') as f:
lines = f.readlines()[4:] # Skip the first four lines
data = []
for line in lines:
parts = [part.strip() for part in line.strip().split('|') if part.strip()]
if len(parts) == 3 and parts[0] != "Date":
date, morning, evening = parts
data_point = [
date,
parse_time(morning),
parse_time(evening, is_evening=True)
]
data.append(data_point)
df = pd.DataFrame(data, columns=['Date', 'Morning', 'Evening'])
df['Date'] = pd.to_datetime(df['Date'], format='%Y-%m-%d', errors='coerce')
return df.dropna(subset=['Date'])
def filter_data(data, start_date, end_date):
mask = (data['Date'] >= start_date) & (data['Date'] <= end_date)
return data[mask]
def plot_graph(data):
plt.style.use('dark_background')
plt.figure(figsize=(10, 6))
plt.plot(data['Date'], data['Morning'], 'r-o', label='Morning')
plt.plot(data['Date'], data['Evening'], 'b-o', label='Evening')
plt.title(f'Time Graph from {data["Date"].min().date()} to {data["Date"].max().date()}')
plt.xlabel('Date')
plt.ylabel('Time (Hours)')
plt.xticks(rotation=0)
plt.grid(True, linestyle='--', alpha=0.6)
plt.legend()
plt.show()
def print_statistics(data):
for period in ['Morning', 'Evening']:
times = data[period].dropna()
if not times.empty:
print(f"{period}: Min={format_time(times.min())}, Max={format_time(times.max())}, Avg={format_time(times.mean())}, Median={format_time(times.median())}")
else:
print(f"{period}: No data available")
def main():
parser = argparse.ArgumentParser(description="Plot time graph from a data file.")
parser.add_argument('--from', dest='start_date', type=str, help='Start date (yyyy-mm-dd)')
parser.add_argument('--to', dest='end_date', type=str, help='End date (yyyy-mm-dd)')
args = parser.parse_args()
data = read_data(FILE_PATH)
start_date = pd.to_datetime(args.start_date, format='%Y-%m-%d', errors='coerce') if args.start_date else data['Date'].min()
end_date = pd.to_datetime(args.end_date, format='%Y-%m-%d', errors='coerce') if args.end_date else data['Date'].max()
filtered_data = filter_data(data, start_date, end_date)
if filtered_data.empty:
print("No data available for the specified date range.")
return
print_statistics(filtered_data)
plot_graph(filtered_data)
if __name__ == '__main__':
main()