.. simplified acceleration calculation to convert to m/s before calculation
.. removed distribution for deltas as they were HUGE and introduced a
terrible performance degradation where aggregation took >30s for a
ride set that previously took <5s.
.. Following on from the recent update to add acceleration
this update adds other derived data series based upon the
rate of change.
.. Added to the ride plot and the CP plot.
Not sure of the overall utility of these updates but bear in
mind that they are targetting sprinting and track users and
analysis.
As well as the positive side of this (development of power
cadence etc) we also want to think about and collect data
on fatigue rate (possibly only power and torque)
- fatigue over time
- fatigue over pedal stroke
.. now can show in zones but using the polarised zones
rather than user defined zones.
.. we may need to revisit this since it uses zone 2 rather
than estimate LT1 from CP.
NOTE: The compare mode needs updating to support this option.
When an interval is added to the compare pane we now
compute the RideFileCache so it can be re-used in the
Histogram and CP charts without computing it each time.
Peak aPower durations now computed and cached;
* updated RideFileCache to work with aPower
* CP curve now allows you to plot aPower
* LTM plot allows you to plot aPower peaks
* DataFilter allows 'best(apower, duration)' function
Updated RideFileCache and LTMWindow/Plot to
plot the user defined durations for peak power.
Actually we support all the different meanmax
measures available in the CP chart, so you can
now track peaks for user defined durations of;
* Power
* Watts per Kg
* xPower
* NP
* Heartrate
* Speed
* Cadence
* Torque
* VAM
I have not spent much time optimising for performance
but reusing the same 'seek' approach used by the recent
update for best() and tiz() functions in the datafilter.
Fixes#322.
.. to make sure the v2 LTMSettings
uses the bestSymbol.
Just pushing this (WIP) to make sure
we don't get half baked LTM settings
from people building against the previous
commit.
.. forgot that the values are converted to
zero decimals when stored.
This fixes strange results when filtering by
wpk or speed, or any series that has decimal
places.
Added static functions to ridefilecache
to get best and tiz values for series and duration
or zones and glued them in to the datafilter code
recently added.
It uses seek (via QDataStream::skipRawData) and is
quite fast on my Linux development PC.
We now need to update the LTM settings dialogs to
the new mockups so we can plot custom durations for
peak power / NP etc too.
NOTE: Not tried on Windows / Mac, so may not be quite
so fast there, will need to check.
To try this out, in the search filter box type:
best(power, 3600) > 250
to filter only those rides where the best hour
power is greater than 250 watts. It should
return almost instantly.
Decoupled classes from MainWindow to reference Context
and Athlete (and introduced a couple of new headers).
We no longer pass around a MainWindow pointer to children
but pass a context instead.
There are still a few pieces left in MainWindow that need
to move to a better place;
* Setting/clearing filter selection
* Working with Intervals
* Adding/Deleting Rides
* Save on Exit
As mentioned previously there are lots of other parts to
this refactor left to do;
* break MainWindow Gui elements into Toolbar and Views
* migrate from RideItem and Ridelist to ActivityCollection
and Activity classes that are not tied into gui elements.
* introduce Application Context and AthleteCollection
Breaking the MainWindow 'god object' into
separate classes for Athlete and Context.
Further updates will need to;
- break MainWindow Gui elements into Toolbar and Views
- migrate from RideItem and Ridelist to ActivityCollection
and Activity classes that are not tied into gui elements.
- introduce Application Context and AthleteCollection
Once these are done we will be in a position to decouple
most classes from mainwindow and also introduce tabbed
athletes.
When the user free text searches or applies a data filter in
the top right toolbar search box it gets applied to any charts
that plot data from many rides, including;
- CP curve
- Calendar
- Histogram
- LTM
- TreeMap
- Summary
I need to update on a Mac to no longer use a Mac text search box
but now use a search filter box on the top right.
This reverts commit 6fdc55528f.
The performance decrease is considerable. Using mallocs across
my personal ride collection takes 5:19 to compute all the caches.
Using the QVector equivalent took 22:40.
Need to consider looking at QVector across the GC codebase.
If an incore cache of an aggregated RideFileCache is invalidated
by a ride in the same period being edited it does not clear
until the cache array is cleared (25 of them so likely to be
never) or upon a restart.
This fixes them being invalidated by refreshCache.
The last of a series of recent patches to address performance
degradation from the introduction of the LTMSiebar. This last
patch introduces a CPX aggregates cache to re-use aggregated
CPX data (e.g. for plotting a specific season or date range).
The cache is set to only hold 25 caches, which should be enough
for most folks list of seasons. But won't get unwieldy if they
scroll around in the diary view.
The following will be introduced in the last patch of
this series:
1. Introduce 'events' within a season and plot them on the
LTM chart -- a form of 'annotation' but also the beginning
of planned events in the future too.
2. Implement click functionality on LTM charts but decide if
we use click to annotate or to define a new date range or
both?
Last part of the search/filter functionality;
* SearchBox now incorporates filter and search
with a new widget. We can update this widget
to include more fancy UI/Interactions without
having to change the ride list or charts etc.
* Added search/filter widget to the relevant charts
and screens; Metrics, TreeMap, CP, Histogram,
Activity Log, Ride list (refactored out of MainWindow)
* Added namedsearches.xml and adding/selecting them
from a drop down menu on the search box.
* Fixed some performance bugs related to duplicate
signals and redraw/reprocessing. Also ensured that
CLucene remains optional -- but means no search or
filter functionality unless it is available.
When the samples in a ride file start from a large offset
e.g. 6hrs is the timestamp for the first sample. The
ridefilecache will compute bests over the initial 6hr
gap.
This patch adjusts the timestamps so they always start
from zero, but only when calculating bests -- it does not
modify the ride data.
We may want to consider 'automatically' fixing this during
ridefile reading, but for now this fixes a nasty bug that
causes GC to hog CPU for large periods of time when computing
the cache.
Fixes#510.
Very basic start, this will now let you plot
VAM on the CP curve. VAM is a measure of climbing
speed and for comparative purposes should be
normalised to the slope climbed.
In this first pass of implementation the VAM metric
is not normalised in any way. It merely represents
the climbing rate, in meters per hour, that was
sustained over each time interval from 5mins to the
ride duration.
If the ride is undulating then only ascension is
included, any time on the flat or descending is
included but meters climbed will be zero. This is
akin to the way we handle power where we include time
when freewheeling.
More sophistication is needed, especially normalising
the value to a common gradient (e.g. 10%). But this
will prove challenging when VAM is comprised of
undulating elements (i.e. gradient is cumulatively
zero, but could contain segments with steep parts).
It may be more appropriate to only measure VAM for
sustained climbing i.e. ignore ride sections when
descending or on the flat.
More thought needed.
Fixes#414.
This is a fix for bug 205 which is registered against v2.1 but
is also present in v3. This fix will not be relevant for v2.1
since the cpi file has been replaced with the cpx file.
Lots of nitty fixups, largely for uninitialised temporary
variables.
I have left the use of boost::function and boost::bind in the
DownloadRideDialog alone, so it will vomit when compiled
with boost 1.46 and gcc 4.5 or higher. Will look into this
more carefully at a later stage.
I am working up to resolving issues identified from -pedantic next.
Mark Rages has developed a super fast and innovative
approach to identifying max-mean intervals. This
approach is 20% faster than the current approach and
importantly does not require "downsampling" of data
yielding much higher resolution for longer intervals.
The code has not been 'adjusted' to adopt QT style
containers (e.g. QVector) and uses malloc/free.
The primary innovations include:
* integrating the data series to reduce the operation
for identifying an interval sum to a single subtract
operation.
* Searching for max sum via a window-search rather
than iterating over the entire series (divide / conquer)
Interestingly, now we have retained high resolution the
xPower algorithm still yields differing results to the
existing metric code. I have contacted Sean to get some
insight into why this might be the case, but suspect it
is related to the implementation of the xPower 25s EWMA.
Tip o' the hat to Mark Rages for this -- sometimes you
just have to accept that no matter how smart you think
you are, there are some folk who /really are/ smart!
The .cpx file used unsigned long to reduce storage
requirements but lost precision. This patch migrates
to using floats, which in most cases are the same size.
One side effect of this update is that mean-max charts
for HR, Speed, Cadence no longer have a 'staircase' effect
and plot more smoothly.
The recent update to plot histograms for seasons or other
date ranges did not support displaying by zone since the
cache did not contain zoned data. This patch fixes that
with an update to RideFileCache to pre-compute and to the
PowerHist class to retrieve and plot.
There are some minor issues that need to be addressed:
* Handling aggregation with different zone schemes
* Deciding which zone scheme to use for the bar labels
when multiple differing schemes have been used within
the date range selected.
* Showing a break down of time in zone by range i.e.
how much time was spent at Threshold when CP was X
as opposed to when it was Y (hint: do it like we
currently display intervals when plotting a single
ride).
* Refreshing the Time In Zone data in the .cpx file
when CP/LTHR changes is not implemented.
The RideFileCache now checks the version of the cache to
determine if it needs to be refreshed -- so no need to
delete old .cpx files before running GC with this patch.
The recent RideFileCache patches added functions to
pre-compute mean-max and distributions. This enabled
this patch to add plotting histograms for a date
range rather than a specific ride.
It supports all the same data series as before but will
allow you to select a season from a new combo box.
I have refactored a fair amount of the code, but kept the
original code in PowerHist as close to unchanged as I could
since I did not want to disturb existing functionality.
There is no support for Zoning historic data -- this requires
an update to the RideFileCache.
The metric code for calculating NP was sub-optimal (actually
it was pretty crap). This patch improves the performance of
the calculation quite substantially (>50% improved).
Additionally, the critical durations code has been adjusted
to reduce the amount of work for long rides (>3hrs or more).
The Skiba and Coggan metrics for xPower and NP
respectively can now be plotted on the CP curve.
There are two issues;
* Downsampling of data to 5s samples skews xPower's EWMA
* Setting scale to start at 30mins breaks the x-axis scale engine
Both issues need fixing, since the first skews xPower upwards and
the second suggests that xPower/NP are meaningful for durations
less than 30 minutes.
Fixes#307.
Peak 1s - 5s critical heartrate was way off the charts and did
not represent the data within the ride file.
Almost certainly caused by the WKO+ file importer, or possibly
by the WKO+ files themselves. It is possible to have ride files
with samples that are shorter than recIntSecs, e.g. where the
recording sample rate is 1s you might see:
Time HR
01:21:32.0 157
01:21:32.7 157
01:21:33.0 157
In this case there are two samples between 1:21:32 and 1:21:33 rather
than the expected one sample. The code to compute averages used the
duration and recIntSecs to determine the average. This patch now
maintains a count instead.
Fixes#319
Many thanks to Gary Smith for helping to diagnose and fix
this error. It is caused by ridefiles that have a gap in
recording at the very start of the ride (i.e. the first
sample is > recIntSecs).
Hopefully this means the CP code is now robust. It is also
worth noting that after fixing the erroneous copy/paste
code in compute() it is now 5 times faster than the original
code and computes 5 times more data series.
Fixes#316.