alex-hhh / activitylog2 Goto Github PK
View Code? Open in Web Editor NEWAnalyze data from swim, bike and run activities
Home Page: https://alex-hhh.github.io/
License: GNU General Public License v3.0
Analyze data from swim, bike and run activities
Home Page: https://alex-hhh.github.io/
License: GNU General Public License v3.0
Now that CP and D' parameters can be set for swimming activities, it would be nice to add a W'Bal plot, like the running and biking one.
This requires some thought, as lap swimming activities don't have 1 second samples (or close) like the run and bike activities have, instead they have one data point for each length. The W'Bal plot would look nicer if it was sampled at 1 second interval.
Map tile loading after loading as finished goes into an infinite loop and seems to keep clearing and loading new tiles.
https://www.dropbox.com/s/z28idqwfnom08tx/simplescreenrecorder-2018-07-02_09.42.06.ogg?dl=0
(video is in my dropbox as it seems github doesn't allow direct attachments of videos here)
Pace values don't average over time (they do over distance). This results in a higher than average pace computed when df-best-avg
is used for the "pace" series, which results in higher estimates for Critical Velocity models.
The Best Avg session inspector and trends plot will need to have some special handling code to detect when the "pace" series is requested, compute the best avg for the "spd" series and convert it back to pace. The "spd" series will correctly average for the Best Avg data.
also swim pace is not considering rest periods -- we neeed a "normalized pace" that takes pauses into account and compute the best avg on that, otherwise the swim pace estimates are too high.
While we're at it make sure that CV can be estimated for the speed series as well
ActivityLog2 implements W'Bal depletion and reconstruction modeling for running activities based on pace and the Critical Velocity parameters. This works nicely if the runs are done on relatively flat ground, but on hilly terrain the model breaks because it does not account for the higher effort of running uphill or lesser effort of running downhill.
A "Grade Adjusted Pace" series could be added to the data frame and the W'Bal series computed off this series. There are several available implementation for the Grade Adjusted Pace, see the link below for a starting point.
https://github.com/gerhardol/trails/wiki/Features#grade-adjusted-pace
https://medium.com/strava-engineering/an-improved-gap-model-8b07ae8886c3
i just build from source with no problems...When i try to import a new activity from a FIT file directly downloaded from garmin connect i get an error:
Failed to import 3321552521.fit: #(struct:exn:fail query-exec: cannot convert given value to SQL type
given: '#(267 1661746798 1931485408 1256318200 692797698)
type: parameter
dialect: SQLite #)
i have no clue about that one.
someone can point me out?
thanks
Aaron
The inspector for lap swim activities does not show best-avg plots, even though they are available in the trends view.
The following series are always kept in metric mode: "alt", "calt", "vosc", "pco" (maybe others?) so all the plots use metric values. See [1] for the meaning of these series.
Summary values (e.g lap average) are displayed as imperial when that system is selected.
Trouble is that summary data when detecting various intervals (intervals.rkt) is expecting them to be always in metric (as the summary values are actually converted for imperial for display). We need to do something similar to the way we handle distance and speed ("dst" -- always metric, "distance" -- metric or imperial; "spd" -- always metric, "speed" -- metric or imperial)
[1] https://github.com/alex-hhh/ActivityLog2/blob/master/doc/session-df.md
I am trying to define a new athlete weight setting for today, but the dialog fails to appear and instead I get this stack trace:
/: contract violation
expected: number?
given: #<sql-null>
argument position: 1st
other arguments...:
3600.0
context...:
/home/nickb/src/ActivityLog2/rkt/widgets/widget-utilities.rkt:63:0: w-duration->string
/home/nickb/src/ActivityLog2/rkt/widgets/duration-input-field.rkt:50:4: set-duration-value method in duration-input-field%
/home/nickb/src/ActivityLog2/rkt/dialogs/edit-athlete-metrics.rkt:143:4: setup-new-metrics
/home/nickb/src/ActivityLog2/rkt/view-athlete-metrics.rkt:105:4: on-new
/usr/share/racket/pkgs/gui-lib/mred/private/mrmenu.rkt:250:14: command method in basic-selectable-menu-item%
/usr/share/racket/pkgs/gui-lib/mred/private/mrpopup.rkt:49:38: go
/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt:435:6
/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt:486:32
/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt:634:3
To re-produce:
Build is from current master.
I experience the following stack trace when using the Session Effort dialog. This happens if I select the calculation method, HR Zone.
application: not a procedure;
expected a procedure that can be applied to arguments
given: #f
arguments...:
(object:connection% ...)
1085
context...:
/home/nickb/src/ActivityLog2/rkt/dialogs/edit-session-tss.rkt:293:4: calculate-tss
/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt:435:6
/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt:486:32
/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/dialog.rkt:58:4: show method in dialog-mixin
/usr/share/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization
/usr/share/racket/collects/racket/private/more-scheme.rkt:265:2: call-with-exception-handler
/home/nickb/src/ActivityLog2/rkt/widgets/edit-dialog-base.rkt:154:4: do-edit method in edit-dialog-base%
/home/nickb/src/ActivityLog2/rkt/dialogs/edit-session-tss.rkt:409:4: run method in edit-session-tss-dialog%
/home/nickb/src/ActivityLog2/rkt/dialogs/activity-edit.rkt:186:4: on-edit-tss
/usr/share/racket/pkgs/gui-lib/mred/private/mrmenu.rkt:250:14: command method in basic-selectable-menu-item%
/usr/share/racket/collects/racket/private/more-scheme.rkt:148:2: call-with-break-parameterization
/usr/share/racket/collects/racket/private/more-scheme.rkt:265:2: call-with-exception-handler
/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt:435:6
/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt:486:32
/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt:634:3
The weather API provider used by ActivityLog2 will discontinue their public weather API and we need to find another way to retrieve weather information for imported activities.
Also, this happened before: #33
Weather records stored in FIT files can be imported and displayed by the GUI, reducing the need for a web service for those who have devices that record this data (I could not find how to get my FR945 to record it though...). The implementation has the following limitations:
DarkSky will continue to support existing API keys until the end of 2022, so the current binary release will continue to have weather data until than.
Several other weather services have appeared aiming to replace DarkSky (seemed to be a popular service). Some of these are linked in comments to this issue, to be investigated once I start working on it.
At this time, DS stopped providing new API keys, but existing ones will work until the end of 2021 -- this is a vague date, but their blog post does not have more details.
The current binary release is shipped with an API key and this will continue to work, perhaps for another 12 months or so, but anyone who wants to build their own package won't be able to get weather data.
To make use of a Weather API by activity log, the API needs to provide the following features:
In the text fields, e.g. when editing an activity, copy/paste/cut with Ctrl-C/Ctrl-V/Ctrl-X are not working on Linux.
I tried to figure out how to enable them, but the most I managed to do is add support for paste from Primary selection buffer with middle mouse button click (usually the wheel nowadays).
diff --git a/rkt/al-widgets.rkt b/rkt/al-widgets.rkt
index 00e8e1d..a5e53ce 100644
--- a/rkt/al-widgets.rkt
+++ b/rkt/al-widgets.rkt
@@ -31,6 +31,8 @@
"utilities.rkt"
"widgets/main.rkt")
+(editor-set-x-selection-mode #t)
+
(provide sport-selector%)
Screenshot to illustrate the issue:
I had the font sizes in the Summary boxes increased in the code, but have somehow managed to lose it with the latest git pull.
For the tab selector I increased it in the code with
diff --git a/rkt/widgets/tab-selector.rkt b/rkt/widgets/tab-selector.rkt
index 980853f..fbf0960 100644
--- a/rkt/widgets/tab-selector.rkt
+++ b/rkt/widgets/tab-selector.rkt
@@ -50,7 +50,7 @@
(super-new)
;; Font used to draw the labels
- (define font (send the-font-list find-or-create-font 9 'default 'normal 'normal
+ (define font (send the-font-list find-or-create-font 14 'default 'normal 'normal
#f 'smoothed))
The axis labels and legends in the graphs are similarly a bit small.
I think font size could be made dependent on screen resolution, but I'm not sure how difficult it would be. Clearly some parts of the application already adapt well automatically, could be a widget issue.
use the same technique as for the BAVG trend for working in the background
TSB should be displayed w/ a one day delay, essentially TSB is at start of the day, fitness and fatigue at the end of the day. This could be an option for the trends chart. This seems to be the way Golden Cheetah does it, as well as other web sites.
Sport Zones and Critical Power parameters are defined for a time period, and each activity will use the time zone and CP parameters that were "effective" when that activity was done. However, nowhere in the GUI is it obvious that this is the case, or what the actual zone values are for a particular activity.
It would be nice to have a "Model Parameters" inspector page for a session which would show this information. It should be a "rich text" read-only page like the about page and could use the graphical zone pictures used by the "Export FIT Settings..." page. It could also show CP model estimates for different distances / times (similar to what the trend plot badge shows). Maybe add links to open the edit cp, edit sport zones pages.
Allow overriding parameters for a session only? Will would not work too well with the model...
Now on HEAD, I just noticed that the tiles in the map are not being loaded properly. It felt initially that the tiles were not being loaded at all, but then I looked around and it seems tiles are being loaded (slowly) but quite far from the course itself, which is strange.
Where's the logic in the code to choose the tiles to load? And is there anyway to enable logging of the tile loading? So I understand if this is loading tiles at all or just idle?
When data is changed using the GUI (e.g. a new session is added or imported, or an existing session is updated), an event is created to signal this. Most of the views make use of make-log-event-source
and collect-events
to determine what has changed and just update the relevant data in the view they dislpay. This reduces the need to call the "Refresh view..." menu item or risk having outdated views.
However this is not complete. In particular, we need to:
The Wunderground API we use supports a 4 day forecast with the free API key we use. It would be nice to use this information and display a forecast in the calendar view, similar to what other calendar applications do.
For this to work a default location or weather station will need to be set in preferences, as we cannot really do GEO lookup on a PC.
ActivityLog2 calculates disproportionately large ascent/descent values for my runs which are typically very flat otherwise. I have Garmin 910xt watch with barometric altimeter.
I'll try to illustrate the problem on a 2km run, for which ActivityLog calculates 58m elevation gain, although in reality there should be no more than 1-2 meter change. There are two Elevation (m) charts:
I'm guessing ActivityLog2 takes 2. for the ascent/descent calculation. Is it possible to influence this?
I'm not sure why it is so wacky even though it's from a flat road, possibly the sensor is broken as it's a pretty old watch.
Thanks
Garmin HRM-Tri and HRM-Swim Heart Rate monitors can record HR data for swimming activities. These devices store the data on the monitor itself while submerged and it is sent to the main device at the end of the activity. The resulting FIT files record the HR data as additional FIT files appended to the main one. These are called chained FIT files in the documentation.
The main issue is that normal FIT lap swim activities only record pool lengths and no data during the crossing of that pool length. We only store one pseudo track point for each lentgth which is needed as only track points can record distance. The lap swim data is in the length entry and data frames for swim activities hold lenghts and not track points.
This will have to play nice w/ the swim lap editor. In HR data will be time based and we will have to correlate it somehow with the rest of the activity which is lap/length based.
Update (27 Aug 2021) Pull request #75 added support HR data in lap swim activities, the following are remaining tasks:
Hi, sorry for this question using issues but I can't find a mailing list or another place for them.
I think I am missing something. You have the CP/W'/Tau model but how does this fit with existing FTP results. Say I do an FTP test using trainerroad.com and want to input the result. How can I go about doing this?
Also, it says in the critical power docs that it can determine these values from a ride but I cannot seem to find a way to do it. Could you please give me some pointers on these two issues please?
Currently, the time of the activity is shown in the local time zone of the computer that ActivityLog2 runs on. For example, this means that ActivityLog2 will show that a Run stared at 3am even though it was 9am in the timezone where the run was actually done.
For activities what have GPS data we could have a function lat/lon->time-zone
to determine the time zone automatically. For other activites (e.g. Lap Swims), we could allow the user to set this information.
Need to determine how would this work for reports and trend charts? Does it matter?
Some links:
File -> Import activity... does not save the last directory from which an activity was imported. Each time the dialog is reset to selecting from a list of recent files, which is useless. On Linux at least all fit files from the watch get downloaded to a single large directory, so I have to navigate to this directory for every activity over and over again.
I suspect on Windows each download creates a new directory, seeing also that "Import from directory..." has a dedicated shortcut. I'd similarly add a shortcut for "Import activity...", this is what I did for Ctrl+Shift+I:
diff --git a/rkt/toplevel.rkt b/rkt/toplevel.rkt
index 2594555..77bb653 100644
--- a/rkt/toplevel.rkt
+++ b/rkt/toplevel.rkt
@@ -172,6 +172,8 @@
(new menu-item%
[parent file-menu] [label "Import &activity..."]
+ [shortcut #\I]
+ [shortcut-prefix '(ctl shift)]
[callback (lambda (m e) (send toplevel on-import-activity))])
Finally, I'd propose a small feature for the roadmap that would reduce activity import friction to almost zero: "Import most recent files". It would work as follows:
When any one of the dialog boxes are closed (either save or cancel), the main application window moves to the bottom of the window stack, behind all other application windows. This is on Windows platform.
The main window should regain focus after the dialog box is closed.
Trend plots can display Critical Power curves by estimating CP params for the data. The Best Avg plot for a session view could display the CP curve for the model defined for the activity. It should also display model and actual values for different times, just as it is done on the trends plot.
I've gotten a Stryd running pod recently, which records power and a few other running dynamics metrics.
With Garmin watches it records the data in some third-party IQ fields in the FIT file I believe, so it will need some custom code to parse it correctly. If you point me to where in the code is the parsing done, I can try to figure out how to extract this Stryd data.
I'm on NixOS
$ racket --version
Welcome to Racket v7.1.
$ git clone ...
$ racket build.rkt # Couldn't find glib, and didn't want to mess with nix-shell
$ racket run.rkt # Chose File -> Import
SIGSEGV MAPERR si_code 1 fault on addr (nil)
[1] 18806 abort racket run.rkt
I tried importing a large activity, which for some reason didn't seem to import. It was not shown in the activities tab. I then tried again but it said that it was already imported so I forced reimport.
After forcing the reimport the activity shows up in the activities tab, but older ones do not. Not sure what else I can add here to help with debugging, please let me know.
I usually run with a Stryd so today I decided to import one of my runs...
ActivityLog2 detected my power meter in equipment. Hurray!
But unfortunately none of the stats/charts/scatter allow power to be selected. I am happy to add this feature to ActivityLog2 if you provide some background on where this data is kept how the charts are generated. Thanks.
Add support for exporting data as well as dual scatter plots (for Torque Efficiency and Pedal Smoothness series)
building.md
mentions one should get a Wunderground API key for weather, however as of May 15, 2018, Wunderground stopped providing free keys.
Complete announcement is here: https://www.wunderground.com/weather/api/
To improve our services and enhance our relationship with our users, we will no longer provide free
weather API keys as part of our program. If you have been directed to download our Weather
Underground free API key by a third party provider, please contact your vendor for resolution.
This is very annoying, I wonder if there's an alternative service one can use.
The Trends Best Avg plot can display a "Model and Data Bests" snip when Critical Power values are estimated. This snip can be dragged around the plot and there is some code to remember the position of the snip. Occasionally, the position is not correctly remembered and the snip is placed at the default position.
To reproduce:
Dragging items in the calendar currently does nothing (the snips move back to their position). I suspect the snip management logic in the calendar view is faulty -- this view was the first time I used a pasteboard%, the code could do with a review...
It is tedious to manually setup CP trend plots and update the CP data with the resulting values. This workflow is indented for determining current CP values, or ones for an entire season and does not work well if there is already a large amount of historical data present in the database.
A mechanism could be added to quicly estimate historical CP parameters. This could work as follows:
All this should be given some GUI which would allow updating the CRITICAL_POWER table. Think about erasing/restoring previous data.
The algoritm could also run on import and monitor any potential CP changes, prompting the user to update them.
Is this something that could be calculated and shown in a column for running activities with heart rate data?
I have a small python script that can calculate it given a FIT file, would be nice if it could be integrated into ActivityLog2 though.
from fitparse import FitFile
def compute_frac_trimp(seconds, hr, minhr, maxhr, gender):
minutes = seconds / 60.0
hrr = (float(hr) - minhr)/(maxhr - minhr)
ret = minutes * hrr * 0.64 * math.pow(2.71828, gender * hrr)
return ret
def compute_trimp(file_name, minhr, maxhr, gender):
ret = 0
hr = None
ts = None
old_ts = None
fitfile = FitFile(file_name)
for record in fitfile.get_messages('lap'):
sport = record.get_value('sport')
if sport != SPORT:
return 0
for record in fitfile.get_messages('record'):
for record_data in record:
if record_data.name == 'heart_rate':
hr = record_data.value
elif record_data.name == 'timestamp':
old_ts = ts
ts = time.mktime(datetime.datetime.strptime(str(record_data.value), "%Y-%m-%d %H:%M:%S").timetuple())
if old_ts and hr:
trimp = compute_frac_trimp(ts - old_ts, hr, minhr, maxhr, gender)
ret += trimp
return ret
The application contains several parts which might be useful as independent packages:
These would be:
Following my pursuits to using ActivityLog2 to determine my CP, W', etc I tried creating a trend chart of best avg as mentioned in critical-power.md
. However I am getting:
instantiate: no argument for required init variable
init variable name: trend-chart-class
instantiated class name: trend-chart-pane%
context...:
/home/pmatos/installs/racket-6.12/collects/racket/private/class-internal.rkt:4610:0: obj-error35
/home/pmatos/installs/ActivityLog2-rel-1.5.0/rkt/view-trends.rkt:186:2
/home/pmatos/installs/racket-6.12/collects/racket/private/class-internal.rkt:3553:0: continue-make-object
/home/pmatos/installs/racket-6.12/collects/racket/private/class-internal.rkt:3507:0: do-make-object
/home/pmatos/installs/ActivityLog2-rel-1.5.0/rkt/view-trends.rkt:340:4: on-new-chart
/home/pmatos/installs/racket-6.12/share/pkgs/gui-lib/mred/private/wx/common/queue.rkt:428:6
/home/pmatos/installs/racket-6.12/share/pkgs/gui-lib/mred/private/wx/common/queue.rkt:479:32
/home/pmatos/installs/racket-6.12/share/pkgs/gui-lib/mred/private/wx/common/queue.rkt:627:3
Hey, when trying to import a .fit file I get this error :
Failed to import C:\Users\Wanted\Downloads\50_minutes.fit: #(struct:exn:fail:contract hash-ref: no value found for key
key: 143 #)
Thank you.
This happens occasionally, and I don't have the steps to reproduce, but, occasionally, the histogram options don't seem to be in sync with what is drawn in the plot. For example, "color by zone" is applied to the histogram when the respective checkbox is not selected, or the outliers are not trimmed when there is a percentage in the "trim outliers" input field. Need to review the code to determine what is going on.
Joe Friel describes a method for determining the heart rate, pace and power zones for an athlete. [1]. This involves doing a test workout and analyzing this workout to determine the Functional Threshold Heart Rate and Power.
There is already some Racket code [2] to do the analysis for running activities to determine Heart Rate and Pace zones, but this has to be run manually in a Racket REPL, so it is not very user friendly.
[1] https://www.trainingpeaks.com/blog/joe-friel-s-quick-guide-to-setting-zones/
[2] https://github.com/alex-hhh/ActivityLog2/blob/master/etc/fthr-analysis.rkt
Downloaded 1.5.0 on Linux as a tarball. Ran racket run.rkt
and got:
file-size: cannot get size
path: /home/pmatos/ActivityLog2-rel-1.5.0/./build-id.txt
system-error: No such file or directory; errno=2
Is this supposed to exist or do I need to bootstrap something?
Currently both session and trend swim plots just take all the lengths into consideration. It would be nice if we could filter them by stroke type, freestyle, breaststroke, etc
Needs to be done in the session plots: scatter, histogram, and quadrant
... and also in the trend plots, where a "Stroke Type" selector should be displayed, when the selected sport is "Lap Swimming"
Garmin devices can use FIT Workout files to guide the user through a workout. ActivityLog2 already supports generating these FIT workout files but the user has to write a Racket program and run this [1]
A GUI for creating and editing these workouts would be nice.
[1] https://github.com/alex-hhh/ActivityLog2/blob/master/etc/my-workouts.rkt
Heat maps are maps which display GPS routes from a selected list of activities. The routes that are more frequently traversed are shown at a higher intensity than the rest. This provides nice map visualizations (although it has questionable value for training).
There is already some functionality for this in ActivityLog2: you can use the "File/Generate Heat Map..." menu which outputs a HTML file with the heat map using Google Maps and their heat map API. This was written before "Trends" were implemented.
It would be nice to have this option as a Trend Chart.
At this time all trend charts are plot snips, so we could change this by implementing the map widget as a snip% and inserting it into the plot.
Hi,
Please find perfectly valid workout files from a garmin forerunner 245 device.
They give the following error message in a console window opened by the software when I try to import it:
Workouts.zip
dict-ref: no value for key: 'duration-value in: '((target-value . 0) (8 . #"") (message-index . 0) (name . #"") (duration-type . open) (target-type . open) (intensity . warmup))
observed with ActivityLog2 version 1.10.0.547
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.