Last active
November 9, 2024 13:49
-
-
Save zdimension/8bf11dd61a6e18f70ddad9f47fdecef6 to your computer and use it in GitHub Desktop.
wrote this code quickly, didn't spend any time making it look good, a third is probably copilot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
import sys | |
from datetime import datetime, timedelta | |
def parse(d): | |
return datetime.fromisoformat(d) | |
def proc(d): | |
s, e = map(parse, d) | |
return e - s | |
#f = json.load(sys.stdin) | |
# for all folder in current folder | |
import os | |
f = [] | |
for folder in os.listdir(): | |
if not os.path.isdir(folder): | |
continue | |
# for each json file | |
for file in os.listdir(folder): | |
if not file.endswith(".json"): | |
continue | |
with open(os.path.join(folder, file), encoding="utf-8") as fp: | |
try: | |
data = json.load(fp)["timelineObjects"] | |
except: | |
print(file) | |
raise | |
for obj in data: | |
if act := obj.get("activitySegment", None): | |
if act.get("activityType") == "WALKING": | |
if "distance" in act: | |
dist = act["distance"] | |
elif "waypointPath" in act: | |
dist = act["waypointPath"]["distanceMeters"] | |
else: | |
continue | |
d = act["duration"] | |
d = (d["startTimestamp"], d["endTimestamp"]) | |
speed = (dist / 1000) / (proc(d).total_seconds() / 3600) | |
if speed > 15: | |
continue | |
f.append((dist, d)) | |
import numpy as np | |
import pytz | |
walk_data = [((dist / 1000) / (proc(d).total_seconds() / 3600), d[0]) | |
for (dist, d) in f | |
if dist > 100 and parse(d[0]) >= datetime(2015, 9, 1, tzinfo=pytz.utc) and parse(d[0]) <= datetime(2025, 6, 30, tzinfo=pytz.utc)] | |
walks = np.array([x[0] for x in walk_data]) | |
med = np.median(walks) | |
print(med) | |
print(np.average(walks)) | |
walks = walks[walks > 1] | |
print(walks) | |
import matplotlib.pyplot as plt | |
ax = plt.subplot(111) | |
ax.hist(walks, bins=45) | |
ax.grid('on', linestyle='--', linewidth=0.5) | |
ax.set_xlabel("Walk speed (km/h)") | |
ax.set_ylabel("Walk count") | |
# export to high quality png | |
plt.savefig('walk.png', dpi=300) | |
# write histo data to json | |
with open("walk.json", "w") as fp: | |
hist, bins = np.histogram(walks, bins=45) | |
json.dump({"hist": hist.tolist(), "bins": bins.tolist()}, fp) | |
# average walking speed per year | |
from collections import defaultdict | |
walks_per_year = defaultdict(list) | |
for dist, date in f: | |
year = (parse(date[0]) - timedelta(days=9*30)).year | |
walks_per_year[year].append(dist / 1000) | |
av_per_year = {year: np.sum(dists) for year, dists in walks_per_year.items() if year >= 2017} | |
# plot average walking speed per year | |
plt.clf() | |
ax = plt.subplot(111) | |
ax.bar(av_per_year.keys(), av_per_year.values()) | |
with open("yearly.json", "w") as fp: | |
json.dump(av_per_year, fp) | |
ax.grid('on', linestyle='--', linewidth=0.5) | |
ax.set_xlabel("School year") | |
ax.set_ylabel("Distance walked (km)") | |
plt.savefig('walk_per_year.png', dpi=300) | |
walks_per_month = defaultdict(list) | |
for dist, date in f: | |
if date[0] < "2017-09": | |
continue | |
adjusted = date[0][:len("yyyy-mm")] | |
if dist / 1000 > 10: | |
print(date, dist / 1000) | |
walks_per_month[adjusted].append(dist / 1000) | |
av_per_month = {month: np.sum(dists) for month, dists in sorted(walks_per_month.items(), key= lambda x: x[0])} | |
print(av_per_month) | |
plt.clf() | |
ax = plt.subplot(111) | |
#ax.bar(av_per_month.keys(), av_per_month.values()) | |
# area under line | |
ax.fill_between(list(av_per_month.keys()), 0, list(av_per_month.values()), color="skyblue", alpha=0.4) | |
with open("monthly.json", "w") as fp: | |
json.dump(av_per_month, fp) | |
ax.grid('on', linestyle='--', linewidth=0.5) | |
ax.set_xlabel("Month") | |
ax.set_ylabel("Distance walked (km)") | |
plt.savefig('walk_per_month.png', dpi=300) | |
vals = list(av_per_month.values()) | |
# get 3-month moving average | |
WIDTH = 3 | |
#WEIGHTS = np.ones(WIDTH) / WIDTH | |
WEIGHTS = np.array([0.25, 0.5, 0.25]) | |
moving_avg = [np.average(vals[i-(WIDTH//2):i+(WIDTH//2)+1], weights=WEIGHTS) for i in range(WIDTH//2, len(vals) - WIDTH//2)] | |
plt.clf() | |
ax = plt.subplot(111) | |
ax.plot(list(av_per_month.keys())[WIDTH//2:-(WIDTH//2)], moving_avg) | |
ax.grid('on', linestyle='--', linewidth=0.5) | |
ax.set_xlabel("Month") | |
ax.set_ylabel("Distance walked (km)") | |
plt.savefig('walk_per_month_moving_avg.png', dpi=300) | |
with open("moving_avg.json", "w") as fp: | |
json.dump(dict(zip(list(av_per_month.keys())[1:-1], moving_avg)), fp) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
import sys | |
from datetime import datetime, timedelta | |
def parse(d): | |
return datetime.fromisoformat(d) | |
def proc(d): | |
s, e = map(parse, d) | |
return e - s | |
#f = json.load(sys.stdin) | |
# for all folder in current folder | |
import os | |
import xml.etree.ElementTree as ET | |
f = [] | |
for file in os.listdir("Activités"): | |
if not file.endswith(".tcx"): | |
continue | |
with open(os.path.join("Activités", file), encoding="utf-8") as fp: | |
tree = ET.parse(fp) | |
root = tree.getroot() | |
for act in root.iter("{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}Activity"): | |
# if attribute sport = walking | |
if act.attrib["Sport"] == "Walking": | |
# get child lap | |
lap = act.find("{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}Lap") | |
start_time = lap.attrib["StartTime"] | |
dist = float(lap.find("{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}DistanceMeters").text) | |
time = float(lap.find("{http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2}TotalTimeSeconds").text) | |
d = (parse(start_time).isoformat(), (parse(start_time) + timedelta(seconds=time)).isoformat()) | |
speed = (dist / 1000) / (time / 3600) | |
if speed > 15: | |
continue | |
f.append((dist, d)) | |
import numpy as np | |
import pytz | |
walk_data = [((dist / 1000) / (proc(d).total_seconds() / 3600), d[0]) | |
for (dist, d) in f | |
if dist > 100 and proc(d).total_seconds() > 300 and parse(d[0]) >= datetime(2015, 9, 1, tzinfo=pytz.utc) and parse(d[0]) <= datetime(2025, 6, 30, tzinfo=pytz.utc)] | |
walks = np.array([x[0] for x in walk_data]) | |
med = np.median(walks) | |
print(med) | |
print(np.average(walks)) | |
walks = walks[walks > 1] | |
print(walks) | |
import matplotlib.pyplot as plt | |
ax = plt.subplot(111) | |
ax.hist(walks, bins=45) | |
ax.grid('on', linestyle='--', linewidth=0.5) | |
ax.set_xlabel("Walk speed (km/h)") | |
ax.set_ylabel("Walk count") | |
# export to high quality png | |
plt.savefig('walk.png', dpi=300) | |
# write histo data to json | |
with open("walk.json", "w") as fp: | |
hist, bins = np.histogram(walks, bins=45) | |
json.dump({"hist": hist.tolist(), "bins": bins.tolist()}, fp) | |
# average walking speed per year | |
from collections import defaultdict | |
walks_per_year = defaultdict(list) | |
for dist, date in f: | |
year = (parse(date[0]) - timedelta(days=9*30)).year | |
walks_per_year[year].append(dist / 1000) | |
av_per_year = {year: np.sum(dists) for year, dists in walks_per_year.items() if year >= 2017} | |
# plot average walking speed per year | |
plt.clf() | |
ax = plt.subplot(111) | |
ax.bar(av_per_year.keys(), av_per_year.values()) | |
with open("yearly.json", "w") as fp: | |
json.dump(av_per_year, fp) | |
ax.grid('on', linestyle='--', linewidth=0.5) | |
ax.set_xlabel("School year") | |
ax.set_ylabel("Distance walked (km)") | |
plt.savefig('walk_per_year.png', dpi=300) | |
walks_per_month = defaultdict(list) | |
for dist, date in f: | |
if date[0] < "2017-09": | |
continue | |
adjusted = date[0][:len("yyyy-mm")] | |
if dist / 1000 > 10: | |
print(date, dist / 1000) | |
walks_per_month[adjusted].append(dist / 1000) | |
av_per_month = {month: np.sum(dists) for month, dists in sorted(walks_per_month.items(), key= lambda x: x[0])} | |
print(av_per_month) | |
plt.clf() | |
ax = plt.subplot(111) | |
#ax.bar(av_per_month.keys(), av_per_month.values()) | |
# area under line | |
ax.fill_between(list(av_per_month.keys()), 0, list(av_per_month.values()), color="skyblue", alpha=0.4) | |
with open("monthly.json", "w") as fp: | |
json.dump(av_per_month, fp) | |
ax.grid('on', linestyle='--', linewidth=0.5) | |
ax.set_xlabel("Month") | |
ax.set_ylabel("Distance walked (km)") | |
plt.savefig('walk_per_month.png', dpi=300) | |
vals = list(av_per_month.values()) | |
# get 3-month moving average | |
WIDTH = 3 | |
#WEIGHTS = np.ones(WIDTH) / WIDTH | |
WEIGHTS = np.array([0.25, 0.5, 0.25]) | |
moving_avg = [np.average(vals[i-(WIDTH//2):i+(WIDTH//2)+1], weights=WEIGHTS) for i in range(WIDTH//2, len(vals) - WIDTH//2)] | |
plt.clf() | |
ax = plt.subplot(111) | |
ax.plot(list(av_per_month.keys())[WIDTH//2:-(WIDTH//2)], moving_avg) | |
ax.grid('on', linestyle='--', linewidth=0.5) | |
ax.set_xlabel("Month") | |
ax.set_ylabel("Distance walked (km)") | |
plt.savefig('walk_per_month_moving_avg.png', dpi=300) | |
with open("moving_avg.json", "w") as fp: | |
json.dump(dict(zip(list(av_per_month.keys())[1:-1], moving_avg)), fp) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment