Compare commits

...

1 Commits

Author SHA1 Message Date
Thomas Klaehn
7d7ca2b48f bicycle-statistics: add accumulated distances view 2019-06-16 20:49:12 +02:00
5 changed files with 67 additions and 34 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
build/
*.gpx
.vscode/settings.json
*.pyc

View File

@ -14,7 +14,7 @@ LOG_FORMAT = "%(asctime)s %(levelname)s %(message)s"
UPDATE_INTERVAL = 60
logging.basicConfig(format=LOG_FORMAT, level=log_level, filename=LOG_FILE)
#logging.basicConfig(format=LOG_FORMAT, level=log_level)
# logging.basicConfig(format=LOG_FORMAT, level=log_level)
log = logging.getLogger('bicycle-statistics')
def parse_args():

View File

@ -47,6 +47,46 @@ def plot_bar_chart(labels, ticklabels, values, title, xlabel, ylabel, filename,
plt.savefig(filename)
plt.close('all')
def plot_line_chart(values, ticklabels, title, xlabel, ylabel, filename, xtick_rotation=0):
'''Plot a line chart.
Args:
values (dict): key: line name
value (list): line values
ticklabels (list): Names for the tick labels (must be same length as value list).
title (str): Title of the chart.
'''
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.grid(zorder=0)
ax1.spines["top"].set_visible(False)
ax1.spines["bottom"].set_visible(False)
ax1.spines["left"].set_visible(False)
ax1.spines["right"].set_visible(False)
plt.title(title)
plt.xlabel(xlabel)
plt.ylabel(ylabel)
for key in values.keys():
if len(ticklabels) == len(values[key]):
plt.plot(ticklabels, values[key], label=key)
else:
short_ticklabels = list()
for i in range(0, len(values[key])):
short_ticklabels.append(ticklabels[i])
plt.plot(short_ticklabels, values[key], label=key)
x_base = numpy.arange(len(ticklabels))
plt.xticks(x_base, ticklabels, rotation=xtick_rotation)
plt.legend()
plt.savefig(filename)
plt.close('all')
class Gpx2Html(object):
def __init__(self, infolder, outfolder, logger):
self.logger = logger
@ -67,9 +107,12 @@ class Gpx2Html(object):
self.logger.info("Begin update of png's/html...")
distances = list()
avg_speeds = list()
distances_dict = dict()
for year in self.tracks.years():
distances.append(self.tracks.distances(year))
distances_dict[year] = self.tracks.distances(year)
avg_speeds.append(self.tracks.avg_speeds(year))
self.logger.info("{}: {}".format(year, self.tracks.distances))
plot_bar_chart(self.tracks.years(), MONTH_LABELS, distances,
'Distance', 'Month', 'km',
@ -79,6 +122,26 @@ class Gpx2Html(object):
'Average Speed', 'Month', 'km/h',
os.path.join(self.outfolder, 'avg_spd.png'))
# Accumulated distance:
accumulated_distances = dict()
for year in distances_dict.keys():
accumulated_distance = list()
accumulated_distance.append(distances_dict[year][0])
for i in range(1, len(distances_dict[year])):
accumulated_distance.append(accumulated_distance[i - 1] + distances_dict[year][i])
accumulated_distances[year] = accumulated_distance
current_year = datetime.datetime.today().year
current_month = datetime.datetime.today().month
current_year_distance = list()
for i in range(0, current_month):
current_year_distance.append(accumulated_distances[current_year][i])
accumulated_distances[current_year] = current_year_distance
plot_line_chart(accumulated_distances, MONTH_LABELS,
"accumulated distance", 'Month', 'km',
os.path.join(self.outfolder, 'acc_dist.png'))
end_date = datetime.datetime.today()
start_date = end_date - datetime.timedelta(days=14)
last_n_tracks = self.tracks.tracks(start_date, end_date)
@ -182,6 +245,7 @@ class Gpx2Html(object):
handle.write('<p>\n')
handle.write('<IMG SRC="{}" ALT="Distance">\n'.format('distance.png'))
handle.write('<IMG SRC="{}" ALT="Distance">\n'.format('acc_dist.png'))
handle.write('<IMG SRC="{}" ALT="Distance">\n'.format('avg_spd.png'))
handle.write('<IMG SRC="{}" ALT="Distance">\n'.format('last_14_days.png'))
handle.write('</p>\n')

View File

@ -1,32 +0,0 @@
from watchdog.events import PatternMatchingEventHandler
import threading
class InputObserver(PatternMatchingEventHandler):
def __init__(self, patterns=None, ignore_patterns=None,
ignore_directories=False, case_sensitive=False):
super(InputObserver, self).__init__(patterns, ignore_patterns,
ignore_directories, case_sensitive)
self.lock = threading.Lock()
self.lock.acquire()
self.new_filename = None
self.run_condition = True
# def on_created(self, event):
def on_any_event(self, event):
self.new_filename = event.src_path
self.lock.release()
def get_new_file(self):
self.lock.acquire() # don't release - will be released with next on_created
if self.run_condition == True:
return self.new_filename
else:
return None
def stop(self):
self.run_condition = False
self.lock.release()

View File

@ -10,7 +10,7 @@ NAME = 'bicycle-statistics'
VERSION = '0.2.0'
AUTHOR = 'Thomas Klaehn'
EMAIL = 'tkl@blackfinn.de'
PACKAGES = ['bicycle_statistics', 'gpx_parser', 'gpx2html', 'input_observer']
PACKAGES = ['bicycle_statistics', 'gpx_parser', 'gpx2html']
SCRIPTS = ['example-gpx-parser', 'bicycle-stat']
DAEMON_START_SCRIPT = os.path.join("/lib/systemd/system", "bicycle-stat.service")