Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache processed activities #42

Merged
merged 3 commits into from
Feb 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,5 @@ version.source = "vcs"
local_scheme = "no-local-version"

[tool.isort]
add_imports = "from __future__ import annotations"
profile = "black"
2 changes: 2 additions & 0 deletions src/stravavis/__main__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from . import cli

if __name__ == "__main__":
Expand Down
4 changes: 3 additions & 1 deletion src/stravavis/cli.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import argparse
import glob
import os.path
Expand Down Expand Up @@ -89,7 +91,7 @@ def main():
if os.path.isdir(args.path):
args.path = os.path.join(args.path, "*")

filenames = glob.glob(args.path)
filenames = sorted(glob.glob(args.path))
if not filenames:
sys.exit(f"No files found matching {args.path}")

Expand Down
2 changes: 2 additions & 0 deletions src/stravavis/plot_calendar.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import calmap
import matplotlib.pyplot as plt
import pandas as pd
Expand Down
2 changes: 2 additions & 0 deletions src/stravavis/plot_dumbbell.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import pandas as pd
from plotnine import (
aes,
Expand Down
2 changes: 2 additions & 0 deletions src/stravavis/plot_elevations.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import math

import matplotlib.pyplot as plt
Expand Down
2 changes: 2 additions & 0 deletions src/stravavis/plot_facets.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import math

import matplotlib.pyplot as plt
Expand Down
2 changes: 2 additions & 0 deletions src/stravavis/plot_landscape.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import matplotlib.pyplot as plt
import pandas as pd
from rich.progress import track
Expand Down
2 changes: 2 additions & 0 deletions src/stravavis/plot_map.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from math import log, pi, tan

import matplotlib.pyplot as plt
Expand Down
2 changes: 2 additions & 0 deletions src/stravavis/process_activities.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import pandas as pd


Expand Down
36 changes: 33 additions & 3 deletions src/stravavis/process_data.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
from __future__ import annotations

import hashlib
import math
import tempfile
from multiprocessing import Pool
from pathlib import Path

import fit2gpx
import gpxpy
import pandas as pd
from rich.progress import track


def process_file(fpath):
def process_file(fpath: str) -> pd.DataFrame | None:
if fpath.endswith(".gpx"):
return process_gpx(fpath)
elif fpath.endswith(".fit"):
Expand All @@ -18,7 +21,7 @@ def process_file(fpath):

# Function for processing an individual GPX file
# Ref: https://pypi.org/project/gpxpy/
def process_gpx(gpxfile):
def process_gpx(gpxfile: str) -> pd.DataFrame | None:
with open(gpxfile, encoding="utf-8") as f:
try:
activity = gpxpy.parse(f)
Expand Down Expand Up @@ -64,7 +67,7 @@ def process_gpx(gpxfile):

# Function for processing an individual FIT file
# Ref: https://github.com/dodo-saba/fit2gpx
def process_fit(fitfile):
def process_fit(fitfile: str) -> pd.DataFrame:
conv = fit2gpx.Converter()
df_lap, df = conv.fit_to_dataframes(fname=fitfile)

Expand Down Expand Up @@ -101,9 +104,33 @@ def process_fit(fitfile):
return df


def load_cache(filenames: list[str]) -> tuple[Path, pd.DataFrame | None]:
# Create a cache key from the filenames
key = hashlib.md5("".join(filenames).encode("utf-8")).hexdigest()

# Create a cache directory
dir_name = Path(tempfile.gettempdir()) / "stravavis"
dir_name.mkdir(parents=True, exist_ok=True)
cache_filename = dir_name / f"cached_activities_{key}.pkl"
print(f"Cache filename: {cache_filename}")

# Load cache if it exists
try:
df = pd.read_pickle(cache_filename)
print("Loaded cached activities")
return cache_filename, df
except FileNotFoundError:
print("Cache not found")
return cache_filename, None


# Function for processing (unzipped) GPX and FIT files in a directory (path)
def process_data(filenames: list[str]) -> pd.DataFrame:
# Process all files (GPX or FIT)
cache_filename, df = load_cache(filenames)
if df is not None:
return df

with Pool() as pool:
try:
it = pool.imap_unordered(process_file, filenames)
Expand All @@ -117,4 +144,7 @@ def process_data(filenames: list[str]) -> pd.DataFrame:

df["time"] = pd.to_datetime(df["time"], utc=True)

# Save cache
df.to_pickle(cache_filename)

return df
Loading