.. updated the overview chart to support trend view and summarise
a season or date range.
.. scope now meaningful in the item registry.
.. added a new TopNOverviewItem to view a ranked list of activities
by metric.
.. updated sparkline to plot variable range (>30days)
.. sort and multisort datafilter functions adjusted as caused a
SEGV during testing (sorry not in separate commit).
Some accuracy was lost in an integer divison for speed and cadence in
getCadence and getWheelRPM, the expression was correct but non obvious
in setWheelRPM, and the speed was not reset upon disconnection for
CyclingPower while this service is used for power and speed when present.
All the commands to set the different parameters (weight, wheel size,
gradient or load, wind speed...) are added to BT40Device and
BT40Controller. A separate pull request will add support to actually
take advantage of these parameters, like the cyclist weight, now
available in this and other devices like the Fortius.
[skip appveyor]
Fallback to previous Qt and Python versions available on Homebrew
to until we can compile Qwt with Qt 5.15
Python comes back to 3.7.5 since the upgrade to 3.7.7 triggers a Qt upgrade.
Qt comes back to 5.13.2
Currently, size is computed from the QWidget geometry height in pixels and then used to set the font size in points. In many cases the result is not that bad because, depending on the screen size and resolution, the pizel size is not that far from one point. We now convert from pixels to inch (DPI) and then from inches to points (72 points/inch). This solves the problem of the text being clipped sometimes or the margin being too large.
Since they reset the brackets, defeating their use by wattsAt and
forcing all searches start from the beggining, and generating
problems with ErgTimeRemaining, which depends on rightPoint.
This problems was introduced by 1402f6ad6aFixes#3491
Some nits from recent Overview updates:
* compiler error using 'and' instead of '&&', gcc happy, msvc not.
* kpi overview item default set to CP estimate
* add chart wizard formatting of final page.
.. uses a datafilter program to calculate a kpi and displayed alongside
a progressbar that shows how the value is progressing to a goal.
.. its really useful to compute across estimates, mmp etc without having
to write a custom metric
.. one simple example is to show CP estimates and progress towards
a target CP or 5 minute best, or perhaps weight.
A program to display the internally generated CP estimate using
the Morton 3 parameter model would be:
{ round(estimate(cp3,cp)); }
.. allow edit and remove of existing items on the overview.
.. due to the way widgets are managed by layouts we create the
configuration widgets on demand and they will be deleted
once the dialogs close.
.. this is fine for overview, but will require a significant
level of refactoring once we start adding charts such as
allplot, trends etc to be added to a chartspace.
[publish binaries]
.. 'Add Tile' added to the overview menu - to enable users to
choose and configure tiles to add to the dashboard.
.. ChartSpaceItems should now be registered to a new chart
space item registry, which will eventually replace the
current window registry
.. ChartSpaceItems need to register a method to create new
items with default settings and provide a widget for
configuring themselves.
.. A new config widget has been created to cover the
overview tiles and some gui components for selecting
metrics, metadata fields and ride series have also
been added.
.. In part 2 we need to add the ability to configure
existing tiles and also remove them.
.. still have a problem with chartspaces that have zero items that we
will need to address, but this at least means when we add an overview
it isn't blank.
Fixes#3476
This gives a more Unix-like behavior when GC is launched from
cmd or PowerShell, including --debug output, on release builds.
Fixed#3481
[skip travis]
[publish binaries]
.. context menu action and processing in event loop deletes the widgets
whilst events are being processed for it. So in event processing we
now return immediately after triggering context menus.
.. when editing a series the de-dup check included the series we are
in the process of editing- which of course led to it always detecting
a duplicate.
.. we now exclude the series being edited from being checked as a dupe.
.. duplicate series names cause all sorts of problems with the
internal maps and lookups and must not be allowed.
.. if the user creates/edits to create a duplicate series name
we append '_n' (where n is any number from 1 upwards) to
guarantee we never habe duplicates.
.. commit 28b2428 introduced a regression whereby the searchbox will
expand to fill space which was jarring in chart settings.
.. this commit reinstates a fixed height, but slightly larger to
remain compatible with the mainwindow toolbar.
.. from now charts that add custom actions will need to also add the
action to pull up the chart settings - since it is assumed the
custom actions are overriding the standard approach.
.. fixes a regression from the chartbar context menu on tabs commit
where it is not possible to edit the setting for a trends or a
critical power chart.
The "Ignoring the CSC service for device..." was intended to notify when power
sensor is present the CSC service is ignored since it is redundant and may
cause problems, but it is misleading when there is no CSC or Power service.
Reported in #3471
.. instead of the 'More...' button in the top left of a chart when in
tabbed mode we now have a menu button when you hover over a tab.
.. the menu button activates the chart menu for now, till we refactor
to using a chart space.
.. the 'More...' menu is still available when in tiled mode (we need to
decide what to do there).
Unlike for the cadence value which uses 1/1024 second units, the wheel
revolution value is based on 1/2048 second units [1]. It is easy to
notice the problem when you ride downhill at 25 kph instead of 50kph! In
addition, the speed was initially incorrect because the previous wheel
position value was stale. This would sometimes give the speed of a
rocket for the initial interval and make a jump on the distance of
several km.
[1] Cycling Power Service, Bluetooth Service Specification, Date 2016-05-03, Revision CPS_v1.1, Prepared By Sports and Fitness Working Group, head of page 15.
https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=412770,
When parsing a "distance slope wind" type, a truncate to integers was done
after computation to meters. This involved rounding issues that were
accumulated, and were quite visible when such a file was used to synchronized
with an RLV video (the slope changes happened "too early").
.. the OverviewWindow class has been refactored to extract out the
core dashboard UX/UI into a new class ChartSpace.
.. additionally, a ChartSpace contains a set of ChartSpaceItem which
need to be subclassed by the developer.
.. for the Overview a set of OverwiewItem classes have been introduced
such as RPEOverviewItem, MetricOverviewItem and so on. These are
subclasses of the ChartSpaceItem.
.. The overview window implementation is now mostly configuration and
assembly of a dashboard using OverviewItems and the ChartSpace.
.. This refactor is to enable the ChartSpace to be used as a drop in
replacement for the existing TabView.
.. There are no functional enhancements in this commit, but the
overview chart shouls appear to be unchanged by the user.
Switching from start_index to start_date_local fixes#3457
Since Duration is End-Start+1, End is decremented to match elapsed_time.
fixLapSwims don't rely on Smart Recording being enabled and,
since km is distance at the end of the sample, a correction is added.
Michael Dagenais found this change makes the widgets to play nicer with
Windows Managers and avoids them to get on top of other programs windows.
Minimize and Restore is automatically handled now, so this commit partially
reverts b89019264e, removing MainWindow
state changes tracking, but keeping VideoWindow position tracking.
This is a clean up to remove conditional compilation for all Qt versions
older than the last known to work: Qt 5.9 with Qt WebEngine and Qt Charts.
Includes an update note to INSTALL documents.
When the video widget is scrolled, the MeterWidget windows appeared on
top of the Main Window user interface. Now the visible portion of the
Video Window is tracked and used as a clipping region. This avoids
blocking the controls on bottom toolbar.
Interpolation math fixes: Slope and interpolation behave correctly when
ride point location doesnt change.
In gpx read: do not open same file twice with different read flags.
When the main window is minimized on Linux, the MeterWidgets stay on the desktop.
A signal were added to the main window for state changes.
The VideoWindow connects to that signal and hide/shows the MeterWidgets accordingly.
Currently, when you move the main window, the MeterWidgets do not follow
and become out of place.
On every Telemetry update, check if the real position on screen of the
video window has changed in order to update the position of the meter
widgets. The Video Window can move for several reasons like when
scrolled or when the Main Window is moved. The Meter Widgets are not
clipped like the Video Window by its scroll area parent though.
Elevation widget was showing progress based on distance, which is workout distance and didn't accout for distance change due to skip forward/skip back.
Add routedistance to realtimedata so elevation widget can access it
elevation using routedistance to show progress
Fix uninit iterator in elevation widget paint
Draw route distance in elevation widget
.. estimates(model, cp|ftp|w'|pmax|x|date) - returns a vector of values
for the model selected.
As with the estimate() function, passing a duration value 'x' will
return the PD model estimate for that duration.
.. also removed hard coded model names.
Enable Meter Widgets overlaid on Video Window for Linux
Meter Widgets, with a transparent background over the video window, use
little screen estate while providing all the needed information. They
were added for WIN32 first but actually work fine on Linux with minor
flag adjustments.
.. tests(user|bests, duration|power) - with no parameters will just
return the number of tests in a ride/date range, or with 2 parameters
will retrieve user defined or bests found by algorithm the last
parameter defines if duration (secs) or power (watts) values are
returned.
After this change:
QtMacVideoWindow.h is used only for native macOS video options:
GC_VIDEO_AV (incomplete)
GC_VIDEO_QUICKTIME (obsolete)
Otherwise standard VideoWindow.h is included with the same options for
the three supported OS:
GC_VIDEO_NONE: placeholder for no video, currently used for macOS builds
GC_VIDEO_VLC: basic video control plus videosync, macOS experimental
GC_VIDEO_QT5: basic video control only, macOS experimental
Overlay Widgets only works on Windows with VLC.
Tested with VLC 3.0.8 on the 3 Operating Systems.
.. resample(old, new, yvector) - returns yvector resampled from old
sample rate to new sample rate. Assumes yvector has already been
interpolated or smoothed as needed (see the interpolate function)
For example, resampling to 10s power samples in a user chart:
{
finalise {
t <- samples(SECS);
xx <- seq(head(t,1),tail(t,1),10);
yy <- resample(RECINTSECS, 10, samples(POWER));
}
x { xx; }
y { yy; }
}
.. interpolate(linear|cubic|akima|steffen, x,y, xvalues) - returns a
vector of yvalues for each element in xvalues where the points
in x,y are interpolated using the selected algorithm passed
in the first parameter. e.g:
xx <- samples(SECS);
yy <- samples(POWER);
first <- head(xx,1);
last <- tail(xx,1);
zxx <- seq(first, last, 0.1); # 10ths of a second
zyy <- interpolate(cubic, xx, yy, zxx);
For Windows we use Python embeddable distribution
For Linux the relocatable Python AppImage
Packages included: sip, numpy, pandas, scipy, lmfit and plotly
[publish binaries]
.. added WBAL and WBALSECS as options for the samples() function to
retreive the w'bal value (in joules) and the secs too.
.. seconds are potentially different to the samples(SECS) values as
the w'bal series is always in 1s samples with gaps in recording
accounted for as part of the calculation.
[skip appveyor]
Initially: sip, numpy, pandas, scipy, lmfit and plotly
Deployed Python added to search path
Binaries reference the Python library on Cellar
Related to 2c0ce8f5c5
.. bin(data, bins) - returns a vector of the data binned into bins, any
data less than the first bin will be discarded, and data greater than
the last bin will be included in the last bin.
the returned bin is based upon counts, so will need to be scaled
if want duration in seconds.
e.g:
b <- bins(data, quantiles(data, c(0,0.25,5,0.75,1))) * RECINTSECS;
.. annotate - didn't validate parameters - seemingly inocuous but there
are multiple validators that update leaf->seriesType. When this did
not happen a) syntax errors were ignored (and caused a crash) and
b) functions like samples(POWER) returned the wrong data.
.. annotate - assumed parameters were numeric or string but did not
support vectors.
.. lots of use of 'it' as a variable, overriding the scope of the
DataFilter::eval() function parameter which in a couple of cases
led to SEGV ('it' is used when indexing vectors).
.. quantile(vector, quantiles) - returns quantile values for the vector
passed. quantiles can be a single value, or vector of values. The
quantile is expressed as a value between 0 and 1, where 0.5 would
represent the median. Values outside this range are truncated to
0 or 1.
.. daterange(from, to, expression) - executes the expression setting the
selected daterange as from-to.
.. any expression that honours the trend view date selection will use
the from-to dates provided.
.. for example, to get weight data for a specific daterange:
measures <- daterange("2020/01/01", "2020/05/01",
measures("Body", "WeightKg"));
.. meanmax(SERIES [, start, stop]) - now allows the user to provide a
date range for the meanmax data to collect. This is so you can, for
example, plot a 'last 90 days' curve:
{
finalise {
yy <- meanmax(POWER, Date-90, Date);
xx <- seq(1, length(yy), 1);
}
x { xx; }
y { yy; }
}
.. meanmax(xvector, yvector) - returns a mean-maximal curve in 1s
intervals from the x,y pair passed in.
the data will be truncated where xvector and yvector are different
lengths, negative y values are set to 0 and the entire dataset
will be interpolated where there are gaps (i.e. the data is not
presented in 1s intervals).
.. the vectorized version of best() - returns a vector of either dates
or peak values for given duration, usage:
bests(SERIES, duration [,start [,stop]]) - get the peak values for
the given duration and optional date range
bests(date [, start [, stop]]) - get the dates of the peak values
but no duration needed but can still proved an optional date range.
.. when you use a selection for a vector e.g. vector[x>0] the vector
that is returned does not set result.number to the sum. This breaks
most of the vectorized functions.
.. for example; mean(samples(POWER)[x>0]) should compute NZAP or
non-zero average power, but instead it calculates as 0 due to
the selection sum bug.
.. get the ridefilecach distributions, precomputed distributions of the
main data series (but not all).
.. dist(series, data|bins) - returns vectors of the series data (count
of points for each interval) or the bins.
.. nozero(v1) returns a vector of indexes into v1 for non-zero values.
Whilst it is possible to do this with sapply() this convenience
function is faster - and the use-case crops up very often.
.. the generic plot didn't register quadtrees if it thought they didn't
contain any nodes, but didn't take into account the fact the root
node could contain up to 25 points.
.. last commit didn't avoid the detach() derefernce in a thread because
it used the [] operator which is non-const, instead we should use
QVector::at(int)
.. A few situations that cause race conditions and crashes when metrics
are being refreshed, found whilst testint user metrics.
1. access to QString is not thread-safe, fixed with a const
2. metric vector resizing is needed even if all metrics are zero
3. entire ride interval needs to be computed, assignment in thread
is not thread-safe and was incomplete anyway.
.. match(vector1, vector2) - returns an index of values; for each value
in vector1 it will return the index into vector2 if there. if the
element in vector1 is not found in vector2 no entry will be added to
the returned index.
.. e.g:
a <- c(4,6,9);
b <- c(1,2,3,4,5,6,7,8,9);
d <- match(a,b);
# d now contains 3,5,8 since indexes start from 0
.. mlr(yvector, xvector1 .. xvectorn) - perform a multiple linear
regression and return a vector of coefficients for each x.
.. under the covers the covariance matrix and chi-squared are both
calculated, but discarded. We should make these available to the
user at some point.
.. requires the GNU scientific library, which will become a mandatory
dependency at some point soon.
.. will become a first class dependency, but for now, whilst we
update the build systems it is optional.
.. to enable update gcconfig.pri with
DEFINES += GC_WANT_GSL ## switch GSL support on
GSL_INCLUDES = ## the include path (no -I)
GCL_LIBS = ## -Lpath and -lgsl -lgslcblas -lm or others
.. see gcconfig.pri.in for examples, Linux has been tested.
.. to install this new depdendency:
Linux: sudo apt-get install libgsl-dev
MacOS: brew install gsl
Windows: vcpkg install gsl
.. if there is a python chart in the view, it will crash as setWeb
does not check to see if embedding worked, and is called via the
property system so must always check.
.. due to qt-bug 62285 we need to use local time not UTC for timespec
since qt charts converts to local time internally.
.. this fixes axes starting at 1hr instead of 0h.
* 1 - Add forceSquareRatio to MeterWidget
* 2 - Adjust default colors and add background text.
* 3 - Add Elevation widget, included in default layout visible only on slope mode.
Based on the work done by Vianney Voyer
Co-authored-by: Peter <pkanatselis@gmail.com>
.. RideWindow is no longer required and brings in artefacts that have
security alerts. This code should have been deprecated previously
and was retained in error.
Fixes#3426
* Add VO2 and Ventilation graphs to WorkoutWidget and add settings
* When running tests with VO2 measurements, it can be useful to see a
graph of at least VO2 but also Ventilation to determine when e.g. a
ramp test results in a plateau and can be considered done.
* Make the color of some VO2 measurements configurable.
* Add chart settings to WorkoutWindow, so that plots can be enabled or
disabled. Also add the possiblity to do averaging.
* Use the term Ventilation instead of Respiratory Minute Volume
* Rework to not affect RideFile
Move from using SeriesType from RideFile in order to allow more series
to be added without modifying RideFile.
In recent Qt versions there's support for BLE on Windows, so remove the
check that disables it.
In Qt 5.14.2 and earlier there's a bug which causes problem if you do
certain things in the context that the signals are emitted. This is only
on Windows, and might be fixed in later versions, but use
Qt:QueuedConnection for now to avoid this.
Some more details of this can be found in Qt bugzilla:
https://bugreports.qt.io/browse/QTBUG-78488
.. the while loop limit of 10000 loops is too low, especially when
looping over ride samples.
.. the pd model short names contain spaces and will never work with
the datafilter estimates() function.
.. aggregate(vector, by, sum|mean|max|min|count) - aggregate vector v
grouping by vector by (which will be repeated if too short) using
the function sum .. count to perform the aggregation.
.. returns the aggregated series, modelled on the R aggregate function.
.. week() & weekdate() - week converts a date to weeks since 1900/01/01
and weekdate() converts weeks since 1900/01/01 back to the date at
the beginning of the week.
.. month() & monthdate() - week converts a date to weeks since
1900/01/01 and weekdate() converts weeks since 1900/01/01 back to
the date at the beginning of the month.
.. basically useful for grouping by week and month or other forms
of date arithmetic.
.. for line charts when one curve is shorter than another the code for
calculating the nearest point (along x-axis) didn't account for
negative and positive results from a quick calculation.
.. just needed a little help from our friend std::fabs()
.. measure("group", "field|date") - get the measures or dates of the
measures.
.. enables us to work with measurements independent of activies, but
we probably need a way of controlling interpolation so we can
get a vector that only contains measurement points.
Copied gc-ci-libs.zip to GoldenCheetah/WindowsSDK after removing
deprecated dependencies (kQOAuth and QwtPlot3D) and adding vlc dlls.
Used --version command line option for minimal testing.
.. sorry, but the power profile colors are hardcoded (which is fine)
but they are too dark, so fixed that up.
.. also the overview (until it is configurable) doesn't show total work
or variability index. Which I've added as they are quite useful esp.
work as a proxy for load and calories.
.. working with user charts to plot configured CP versus the trend
in power indexes led to some new code and a few fixups:
* new metric PeakPowerIndex is the best PowerIndex value for the
ride based upon power mean maximal data. It is not computed for
intervals.
* overview chart default config shows the PeakPowerIndex instead
of Power Model which was blank and unimplemented.
* the overview chart was not in the window registry, it must have
been removed by accident in a cut and paste incident
* the 'activity' function is userchartdata was not called, the code
was not included (it iterates over samples, but not activities)
.. When the widget in QScrollArea resizes the position is set to origin,
which is a regression introduced sometime after Qt5.9.
.. If the chart bar was scrolled then dragging a tab would cause the
buttonbar to be resized temporarily as the item is removed from one
index and placed at another.
.. To get around this we make the buttonbar fixedWidth, which means no
resize events or processing occurs. But it means we need to adjust
as widgets are added and removed.
.. Fortunately an existing function 'tidy()' is available to do this for
us, but needed to be controlled (only resize when widgets are added
or removed).
.. If the regression is fixed this commit can be reverted, but it should
be harmless with/without any Qt fix.
.. turns out the stack in homewindow and the "buttons" on the chartbar
all need to be re-ordered to align with the tab index.
.. some poor design in here, but letting it go for now as we will be
replacing the 'HomeWindow' widget in this release cycle anyway.
.. scroll left and right jumped to front/back which assumes there isn't
more than 2 page widths of charts -- this is not always the case.
.. we now scroll a third of a screen full at a time with animation to
give some feedback to the user as we scroll.
.. remove the old scope bar in favour of a more modern sidebar as we
transition the UI to a new design.
.. the newmainwindow approach is not practical, as making 2 UX coexist
at the same time was impossible and would lead to major issues.
.. note a number of views are on the sidebar but disabled, they will
be added over time.
The 2nd parameter of RideItem::getForSymbol is a boolean for metric/imperial,
passing c selects imperial units when metrics(Symbol,...) is used in LTMPlot.
Exiting isRun/isSwim are preserved and new isRide/isXtrain added.
Use them in DataFilter to provide isRide, isRun, isSwim and isXtrain
and in RideSummary for better filtering of activities in rides, runs
swims and xtrains.
Part 1 of #3280
.. metrics(symbol) now supports an optional start and stop date
range.
.. metrics(symbol|date [, start [, stop]]) - where start and stop
are numberically days since 1900/01/01 or can be date strings
such as "2019/12/31" for 31st December 2019.
.. this is to provide an alternative way of working with metrics
that was previously supported with the '[[' and ']]' operators.
.. be consistent with dates and always work with days since
1900/01/01. That way date arithmetic is consistent in the
data filter.
.. the GenericChart converts data to MS since Epoch if the axis
is a date range, in the same way it does for Time axes.
.. basics for Mac native toolbar without title and support
for resize and full screen etc.
.. toolbar is empty and will need cocoa elements added but
will fix up when MS Windows native support is to the
same level.
.. suspect only Linux will use frameless and might move to
accepting the toolbar is present on Linux.
.. simple start just to resolve functions typically performed
by the window manager. Minimise/Maximise.
.. need to resolve resize by dragging sides/corners as well as
drag from full screen.
.. Not 100% convinced this is the right strategy (frameless
window and managing resize/drag within the mainwindow).
.. prototyping a new qmainwindow layout, will only be shown
if you pass --newgui on the command line.
.. there will be lots of commits as this develops across
different platforms and building blocks are put into
place.
.. this is likely to take 2 months or more before it becomes
something usable.
.. the --newgui is for developers only, since there will not
be any usable functionality for quite some time.
Upload/Download are similar to Export/Import in User Metrics config dialog.
Admin interfaces are similar to CloudDB charts for both user (edit/delete)
and curator (set curated/edit/delete).
Name and Description are initialized to the corresponding items for the metric
but both can be edited to provide different/more complete information for the
CloudDB interfase.
Fixes#3361
.. when you change colors in preferences the user chart didn't honor
the new plot marker color and the generic legend did not update the
background color.
.. lowerbound(v, value) - returns the index into v for the first
element that does not evaluate to < value.
This is a binary search modelled after std::lower_bound (and
uses it in the implementation too)
.. need to refresh the user program when it is edited by the user.
the last commit fixed a memory leak in this code but broke it.
.. should think about changing this piece of code and allowing the
userchartdata to accept a new program to process (instead of
it being set in the constructor).
.. curve(series, x|y|z|d|t) - retrieve the data from another curve so
we don't have to recompute it when working with user charts.
if the datafilter is not on a user chart it will return 0. User
needs to ensure the series are ordered correctly for this to work.
.. you can now use algebraic operators with vectors. If a vector
is shorter it is repeated to match, e.g.
a<-c(1,2); b<-c(1,2,3,4,5); d<- a * b;
is calculated as;
d<- c(1,2,1,2,1) * c(1,2,3,4,5) and will yield: 1,4,3,8,5
.. arguniq(list) - returns an index into unique values in the list. the
list does not need to be sorted, the returned list index always
refers to the first item in a list (not the later duplicates).
.. uniq(list [,list n]) - will de-dupe the first list by removing
duplicates. All remaining lists will have the same items removed
by index, in the same way as sort/argsort.
.. meanmax(efforts) - runs the filtering scheme used on the cp plot to
filter out submaximal data; a mixture of comparison to a LR, maximal
from same date considered as an averaging tail and use of power
index.
.. it returns a vector of indexes into the meanmax data for power;
so meanmax(POWER)[meanmax(efforts)] can be used, but since the
index starts at 0, need to add 1 to get seconds.
.. show x-avg on select at the top of a line chart, stops it overwriting
the min/max values. Especially relevant when using a time/date axis
hence limiting to a line chart where this is most common.
.. not neccessary to get out a build just yet, but cycling on the
build number and version string for any development builds
users download from travis or build themselves.
.. allow data labels for points on the chart, added to User, R and
Python chart addCurve() etc.
.. NOTE: opengl painting ignores this setting so should be disabled
for data series that want labels. We do not do this
automatically, but might consider that later.
.. GC.annotate(type="label", series="Power", label="CP=222") added to
the python chart to add a label to the legend for displaying things
like parameter estimates.
.. it does feel like annotations will need to be thought thru and likely
result in a GenericAnnotation class. But lets cross that bridge
when we get there.
.. Label annotations are enough to get started and are now present in
User, R and Python charts.
.. GC.annotate(type="label", series="Power", c("cp", cp))
Provide call for adding label annotations from R to
match the recent update for the user chart.
.. add annotation labels from within a datafilter, ultimately
gets shown alongside the legend in generic plot.
.. this only works from a user chart, so need to add an equivalent
API to call from Python and R.
.. bool(expr) - returns 0 or 1 for the expression passed. This allows a
logical expression to be used in a formula (which is useful when
fitting models).
e.g a*(x>1) is invalid, whilst a*bool(x>1) is not.
.. when editing programs the syntax errors were not being
shared with the user, just a wavy red line.
.. this commit adds the errors to the two main dialogs for
editing user metrics and user charts.
.. in addition a completer was added to the user chart
series editor to help (it already existed on the metric
editor).
.. lm(formula, xlist, ylist) - fits a formula to the x,y data using
the levenberg-marquardt OLS algorithm.
the formula is expressed as any other expression and the starting
values must be set beforehand- this is also reinforced by the fact
the parameters must exist before the formula is declared.
the fit returns a vector [ success, RMSE, CV).
.. an example, to fit the morton 3p model to meanmax would be:
# fetch mmp data
mmp <- meanmax(POWER);
secs <- seq(1,length(mmp),1);
# set starting values, then fit Morton 3p to first 20 min data
cp <- 200; W<-11000; pmax <- 1000;
fit <- lm((W / (x - (W/(cp-pmax)))) + cp,
head(secs,1200),
head(mmp,1200));
.. along the way I needed to refactor the way lmfit is managed and
also corrected banister to avoid threading issues.
.. also snuck in a sqrt() function as needed for testing and was
rather an egregious oversight.
.. when adding symbols to lines or lines to a scatter we
need to show/hide the decoration with the main series.
.. in addition if the decoration is the only thing visible
e.g. symbols for line (with no line style) then still
need to show the hover on the symbols.
.. honour both the symbol and line style settigns for curves. This
means you can have a series on a line chart that is dots and a
series on a scatter that is a line.
.. need to think about best way to manage hover, but suspect it should
only apply when a line chart has a series with no line but has
symbols -- we should hover on them. Currently they are ignored.
.. increasing the precedence for the [ ] symbols resolved the
reduce/reduce issue introduced in commit 1231f59b1a
.. as a result the new rule added in that commit has been
removed.
.. thanks to Ale Martinez for the correct fix.
.. smooth(list, ewma, alpha) - smooth data using an exponentially
weighted moving average. alpha must be between 0 and 1, if not
0.3 is used as a fallback.
.. part of a few updates to add some smoothing algorithms to apply
to vector data, this first one is just a simple moving average.
.. smooth(list, sma, centered|forward|backward, window) will apply
smoothing to the list. Note that centered doesn't use multiple
windows when the window size is even, so recommend always using
an odd number for this parameter.
.. will add ewma and maybe some others over the next few commits.
.. you can now configure if a series is shown on the legend, this is
for lines or curves that are there for illustration but do not
need to be displayed in the legend / hovered.
.. they are rather anachronistic. use of vectors across the datafilter
and the metrics() function replaces them.
.. as a by-product nested indexing works without a syntax error (yes
you could add a space, but most folks would be lost).
e.g. a[b[1]] works as you would expect.
.. expressions like a+b*c[n] were being parsed as equivalent to
(a+b*c)[n] instead of a+b+(c[n]).
.. to resolve this symbol[index] is declared first in the grammar
and whilst it will introduce reduce/reduce warnings that is
actually what we want (we declare it early to override the
definition from expr below).
.. keener yacc wizards might have a more elegant solution for
this one....
.. lr(xdata,ydata) - perform a linear regression returning the results
in a vector of 4 values [ slope, intercept, r2, see ].
.. as a by-product the slope on generic plots now show r2 and see as
they are being calculated by GenericCalculator.
.. need to transform values from MS since Epoch back to seconds
when doing the LR- since we convert when setting up the chart
as Qt wants time based axes to use MS since Epoch (they do not
offer any transformations for the axis).
.. this means that the slope/intercept are now calculated correctly
on charts that use time based axes.
.. whilst its possible to assign to a selection of elements in a
vector e.g. v[c(3,5,7)] <- 99 to assign 99 to el 3,5 and 7
I forgot to update the code to /return/ a vector e.g.;
a <- v[c(3,5,7)]
was not handled at all. This commit fixes that. It means we
can select from a vector element-wise -or- via a logical
expression.
.. sapply(list, expr) - as in R sapply returns a vector of the results
of expression applied to every element in list. Values for x and i
are made available in the expression.
.. v[ lexpr ] - returns a subset of vector v where logical expression
lexpr returned non-zero.
lexpr is evaluated for every element in the vector and has two
variables to work with 'x' is the current element value and 'i'
is the index into the vector (starting from 0).
.. additionally, positional vectors can be used in assign statements
but we did not go so far as to allow selections to do the same in
this commit. that might be fixed later.
.. changed the indexing operators [ ] to work solely with vectors.
so it is now possible to reference an element in a vector:
a<-c(1,2,3,4);
b<-a[1]
will assign the value 2 to variable b.
.. additionally you can assign to an element of a vector, following
on from above:
a[0]<-99;
will mean a how has 4 elements: [99, 2, 3, 4]
.. lastly you can use [] with an expression, so:
c(1,2,3,4)[2]
evaluates as value 3.
.. banister(metric1, metric2, series) - get a vector of banister
data where stress metric1 and performance metric2 are used and
fetch the series which is one of nte,pte,perf,cp or date.
E.g. to get the predicted CP curve using PowerIndex you would
use: banister(BikeScore, Power_Index, cp)
.. pmc(expr, series) work with PMC, generating it from an expression
that is evaluated for every ride (as a stress metric). Returns a
vector of the series specified e.g. pmc(BikeScore, lts)
.. support for axes that are time based, assuming the user has
supplied in seconds starting from 0 (which is true for an
activity).
.. since QT charts requires times to be in MS since Epoch
and we don't know if we need to convert from seconds
until the axis is configured the series data is updated
just before charts are created in GenericChart.
This means that anyone using generic plot directly will
need to do this conversion. For this reason all integration
across the GC codebase should be via GenericChart.
R, Python and now User charts integrate via Generic Chart
so this should not really be an issue.
.. now works on trend view (in rangemode).
.. needed to add daterange to eval in datafilter to provide context
for operations; e.g. meanmax return for activity or daterange.
.. fixed up a few bugs along the way. But now need to resolve the
x-axis in generic plot when using dates and to auto set to some
kind of sensible default.
.. the way data is prepared in a user chart has been redesigned, it now
follows a similar pattern to the user metric program where a number
of functions can be written and will be called at different points.
.. init { .. } can be called to initialise variables
relevant { .. } can be called to shortcut computation
sample { .. } is called for every ride sample
activity { .. } is called for every activity
finalise { .. } is called once iteration completes
x { .. } is called to get the series x values vector
y { .. } is called to get the series y values vector
z { .. } is called to get the series z values vector
d { .. } is called to get the series d values vector (dates)
t { .. } is called to get the series t values vector (times)
.. at present z,d and t serve no real purpose but will be used to
augment data points and be shown on the legend when hovering.
This is a planned future development.
.. meanmax(SERIES) - returns a meanmax array starting from 1s and
length out to longest value available for the selected season.
NOTE: the first point 0s has been removed from the array before
being returned so you do not need to ignore it or remove
it programmatically.
.. for creating and syncing ordered lists.
.. argsort(ascend|descend, list) - will return a sort index in the same
way as numpy.argsort(). It can be used to sort other lists and is in
fact also used internally by sort.
.. sort(ascend|descend, list [,list .. listn]) - sort 1 or more vectors
using the first vector as the set to sort, the remaining lists are
re-ordered together with the first.
this is useful where you may have timeseries data that is related but
in separate vectors- you can sort them together.
.. head(list, n), tail(list, n) do as you'd expect, returning a vector
of length n from the head or the tail. if n is greater than the size
of the vector the maximal sized vector will be returned.
.. samples(SERIES) will return a vector of all datapoints for the
specified series. e.g. samples(POWER) will return a vector of
3600 elements for a 1hr ride with 1s sampling.
.. to make sure it doesn't go haywire and open all ridefiles if
used in a datafilter or in a naive way by users, it will not
open a ridefile, just return an empty vector.
.. this is safe to use in user metrics; e.g. for average power
you could use value { mean(samples(POWER)); } and this would
work well as the ride is opened before calculation starts.
.. there is an added bonus that this means a datafilter:
length(samples(SECS)) will filter only those rides that are
open. A useful debug tool for memory usage from download or
ride import activity.
.. append(a, b [, pos]) follows the R convention for append and
will append b to symbol a, optionally inserting from pos. it
returns the number of elements in a rather than a copy of the
vector (it is supposed to be quick).
.. remove(a, pos, count) has no R equivalent but does what it says
calling the underlying QVector function, so should be quick. It
also bounds checks (does nothing if bound invalid). Just like
append it will also return the number of elements in a after the
operation is completed.
.. some more functions for creating vectors and working with them
.. seq(start,stop,step) - create range vector and negative
values are allowed e.g. seq(1000,1,-1)
.. rep(value, n) - create a vector repeating the same value
n times.
.. length(s) - return the length of the *vector*, so if the
parameter is a single value then the length is zero. this
might change, but for now it seems useful. An object that
is created and updated as a vector will return 1 if it
only contains one element.
.. added the c() function, same syntax as the R function it simply
creates a vector comprised of the parameters passed.
.. if one of the parameters evaluates to a string it will try and
convert to a number. We only support vectors of doubles for
simplicity and ease of implementation.
.. full for scatter, in selection rect for line. Seems a compromise
between providing useful context on a scatter and avoiding lots of
noise on a line chart.
.. mostly complete, following the Python charts lead on the
API and basic UX.
.. some nits left in there; pie/bar chart categories and labels
and an open question on whether/how we let users set the axis
color / leave it alone.
.. paint for whole chart so can compare to data outside of the
selection area (which is probably the most useful thing to
do with the slop line).
.. fixup the paint co-ords which assumed x-axis started at 0.
.. a regression from Qt5.12, native dialogs hang if threads are
in use (!). Not doubt will be fixed, but for now lets avoid
it -- need to revisit this before releasing since the Qt
dialog is horrible. Will add to github issues.
.. turns out the jsonunprotect function wasn't stripping the trailing
spaces that jsonprotect was adding. This caused axis labels to have
spaces at the end that the qt charts code stripped-- so when we went
looking for axis label texts they didn't match.
.. this commit causes jsonunprotect to strip trailing spaces. This
should not result in any regression as use of jsonunprotect is
limited to HomeWindow properties.
.. x-axis label colors
.. y-axis alignment should not be managed upstream
.. still have issue finding hover area which is not
present in the python chart.
.. basic user chart only on analysis view. Users can specify
a data filter script to prepare data for the x and y axes.
It uses the generic chart to visualise so one step closer
to a UX where all charts have the same behaviour.
.. will need to update to place on trends view, including
updating the way userdata works and possibly adding a
few new functions to support working with models and mmp
data amongst a few other things.
.. likely contains quite a few nits as most of the code
is related to configuration and is a bit thorny.
.. setUpdatesEnabled() to stop output did not help at
all with respect to the jarring effet of watching
plots added when in stack mode.
.. for some reason adding this QApplication::processEvents()
fixes that. Go figure.
Use Create Activity in Strava API when there is no samples
Fixes#3363
Also map some known sports to the Strava API equivalents,
we should think about a generalization as part of #3280
Fixup stack view a) minimum height for plots, b) added a
scroll area to manage more plots than fit on the screen
and will layout horizontally or vertically.
Stack charts now when set as an option, in which case all
data series are given their own plot.
Or alternatively, where data series have different x-axis
names, they get a plot for each x-axis.
Need to fixup a) minimum height as can get squashed and
b) scroll area needed as well as c) layout direction.
.. added GenericChart which manages a collection of plots, so
you can plot multiple series stacked (like in AllPlot).
.. additionally added option to set layout vertical or
horizontal, since its useful to layout scatter plots
horizontally where time series will be largely vertical.
.. at this point the code is slightly refactored to add
GenericChart between PythonChart and GenericPlots.
.. will shortly add code to support managing multiple plots
in layouts and adapting if settings change (.e.g the
python script is edited, settings are changed).
.. updated to support different linestyles and also legend can
now be placed above, below, left or right of the chart and
orientated to list series vertically or horizontally.
.. the vertical legend is a bit ugly as nothing lines up, will
fix up separately.
Isolate curves by hovering on axis for scatter and line
charts. Also added horizontal guide line and click to
add horizontal annotations (but not added yet).
Annotations will come later, but added as was the right
part of the code.
Also tidied up a bit of the paint code in selection tool
since it was a bit messy.
.. for some reason in earlier version of Qt Charts there are errant
items in the same area as the axes that are blank, these break
the code that derives the axes rectangles in Qt Charts <= 5.10
.. now we have the axis rectangle (previous commit) we can paint
the cursor values in the axis rather than on the canvas. Lots
of work to fix a cosmetic issue, but damn, it was worth it.
.. amongst a few other nits when a plot is resized or the chart is
being finalised we get the scene rectangle for each of the axes.
This is so we can trap when the mouse hovers over an axis and
also so we can paint the current mouse coordinates on the y-axis
in the scatter plot (they are painted on the canvas at present
and paint over each other causing a nasty artefact).
Will fixup y-value cursor tracking shortly.
Use legend to select which series are plotted by clicking to
show hide a series. Hover just shows a hover background and
does not temporarily isolate the series, this may be something
to consider for later.
Applies to scatter and line charts.
.. created separate source files for the legend and selection tool
classes and removed some of the interdependency.
.. partly because GenericPlot.h and GenericPlot.cpp were becoming
unwieldy and partly to support using the generic legend in
other charts (notably CP, LTM and AllPlot).
The scene was being updated unneccessarily when it was active but
not changing (i.e. selection rectangle was stationary etc).
Added a state variable rectchanged to the selection tool to notify
the updateScene() method that nothing has changed since the last
event. So do nothing.
Added selection on line chart, uses a range selector and
works in pretty much the same way as the scatter rectangle
selector.
I've removed a lot of the calculated values from the plot
since it gets very busy very quickly.
I also noticed there is a significant performance problem
when selections are active- suspect there are a large
number of unneccessary scene updates. Will investigate.
.. when no value present was miscalculating the nearest point to the
cursor on the x-axis because distance was calculated as a large
negative by using a series point value of 0 (when no value was
available). Fixed by just ignoring zero values.
Added hover code to line chart, so get legend values on hover
and marker points as you mouse over the series and an x-axis
label at the bottom to show current x value.
Also added Utils::removeDP() to remove decimal places from a
number string e.g. 24.000 becomes 24, 987.3440500 becomes
987.34405. This is a hack to avoid handling decimal places
in the user settings, but will keep as reduces the amount
of "digital ink" regardless.
Enable accept only when boty symbol and name are non empty
Warn on name and symbol collisions to avoid silently discarded
metrics or metrics not usable from formulas
Complements 635eccd001, related to #2279
.. recent fix to check for points on the boundary (checking with >=
and <= instead of > and <) mean't that items on the boundary
would be inserted into multiple quadrants. This wasn't much of
and issue as only using quadtree for mouse hover, but it is a
bug none the less and needed fixing.
.. compile time warning nits also tidied up for new code, to stop
errors spewing on build and hiding real issues.
The .gmetric file it is the same xml format as usermetrics.xml
with just one metric, on import only the first is imported.
Import is similar to Add with the imported settings prefilled,
so the user can change it before to effectively add it or cancel.
Fixes#2279
TODO: we should check for duplicate symbols on Add/Edit/Import
Added new legend which displays hover over value from the
prior commit. Also fixed up the quadtree issue with some
points being hard to hover.
Need to consider what to do with multiple x-axes; am tempted
to create a new chart for each x-axis since hover and general
interaction gets very messy with multiple x-axes.
Next commit will extend the current functionality onto line
charts before we move onto hover for pie and bar charts.
GoldenCheetah lacks support for splitting multisport fit files.
These files combine multiple sports recorded into a single
activity. Those sports are marked by session entries. These
session entries are parsed but ignored.
Fit files are parsed on-the-fly without caching data. This is
great in terms of memory useage but bad in terms of splitting
the activity into sessions because of the fit specification.
The specification allows session entries to appear either
grouped at the beginning of the file or at the end of the session
spread throughout the file.
We do cache the most relevant data entries along with the
session field entries. This hopefully adds as little overhead
as possible while parsing and in memory useage, but allows
us to determine if there are multiple session entries in one
file. If so, we can split the single file into multiple ones,
each representing a single sport (activity). Eg.: If a triathlon
is recorded using the multisport method it is split up into
the following activities:
- Swim
- Transition
- Bike
- Transition
- Run
This corrects the metric calculation. Prior to this change
the parsed activity is tagged as a run activity and the whole
data - swim/bike HR, bike cadence, ... - was taken into account
for the run metrics calculation. Now only the relevant part of
the file is taken into account.
Laps as well as XData records are also split up to the files
created out of a single multisport file and are aligned in time.
It turned out that it is best to treat transitions as run.
Fixes: #3211
Doing shallow copies of Objects when explicitly declaring a copy c-tor
is very dangerous.
When the object is cloned, the second to be destroyed crashes w/ double
freeing memory or/and, even worse, dangling pointers are left around.
That in turn leads to unpredictable crashes.
There's only one thing left to say, use smart pointers wherever
possible. Or simply do not use arrays of pointers. The vector class
already get it right to alloc/free memory for objects stored in it.
Hover now wired into the SelectionTool with scatter points
being highlighted as you move the mouse. The code to select
nearest neighbours looks correct, but in practice it can
be hard to select some points (this needs further investigation).
Highlighting the selected point is done in the paint method
of the selection tool (its just one dot), but zorder issues
with opengl accelerated series means it appears underneath
we may need to create a curve with one point to avoid this
(this also needs further investigation).
Need to work next on a legend widget of our own to manage
the hover display and axis interaction (and better aesthetics
than the standard offerings).
When curves are painted via openGL there are a number of limitations
regarding aesthetics, setColor() doesn't work once the series is
created, opacity is ignored etc.
So when we create a selection from an openGL enabled curve we cannot
set it gray etc. Instead, this commit will set the selection curve
to gray and use opengl rendering on the selection (on the assumption
that the user specified opengl rendering for performance and so we
should reflect that in the selection curve).
This has a dramatic improvement in performance on a scatter plot of
activity data where there are 1000s and 10000s of points in some
cases.
We should recommend that opengl is enabled for curves that have large
number of points, and indeed, the default is to enable it unless the
user specifically overrides (e.g. for better aesthetics).
Added Quadtree for identifying points on the plot when
hovering with mouse, but should also be reused for the
rect selection tool (it currently iterates over all points
for a series).
This commit just adds basic algorithm will need to follow
up with a) refactor it into the selection tool and
b) display the hover value somewhere (legend?)
The hash near constant time vs linear search in pass method
speeds up considerably operations s.t. seasonMetrics in R and Python
APIs when there are lots of activities, since they were O(n^2) otherwise.
.. the chart was being redrawn as series added because initialiseChart()
was removing axes, be waiting until finaliseChart() to do this we
avoid the flicker.
.. My eyes! My eyes! Tuft would not be impressed with all the
extraneous plotting and noise from the selection tool that
detracted from the data.
Have removed the guide lines, limited the slope line to the
selection rectangle, and toned it down as well as making the
selection rectangle more subtle when its not being manipulated.
SelectionTool now calculates a bunch of useful values
for the selected items (mean, min, max etc) and they
are plotted with guidelines on the scatter plot wehen
a selection is active.
Added a rectangle selection tool for scatter charts. Click on
the canvas and drag to highlight points of interest and click
on rectangle to drag around, resize with wheel events.
Additionally, improved some of the aesthetics on axes and labels
etc to make the chart look and feel similar to the rest of the
qwt based charts.
There are likely to be a large number of commits for part 3, to
cover auto calculation of mean/max/sum/regree for selected points
and extend to other types of selections and apply to other chart
types.
.. the qchart code is now becoming more generic, with interactivity
and generalised rendering so refactored out into its own class
before adding too much more code.
.. this is also because we will be creating a generic chart for users
to plot their own 'userdata' (currently in allplot/trends charts)
using this generic plot and want to have a common widget for this
to get a more consistent and less jarring user experience.
Support training with Tacx TTS files:
TTS distance and gradient are honored meaning training
load should exactly match tacx. Ride altitude is recomputed
based on distance and gradient, so training work will
match The Tacx Experience and might not match reality.
When TTS file contains no location, altitude is still computed
from distance and gradient but will start from 0.
Gradient during training is interpolated from distance and
altitude so will change smoothly while summing perfectly
to the correct load.
The TTS Reader source was adapted from the WattzApp
Community Edition java source.
Highly recommended that 'Use Simulated Speed' option
is enabled when riding TTS files.
This change was only tested against a small number of
dvds that I own. I would appreciate feedback and problem
reports. I would especially appreciate anyone that can
compare this behavior against Tacx as I only tested with
my Wahoo Kickr.
Issues and Future work:
I guessed about how to set starting distance and might
have got it wrong.
TTS Files contain video synchronization data. Currently
this is ignored and rlv file must be specified. I've not
even looked at the video sync data and no idea if it is
better than the rlv.
There are data fields in the TTS that Ive not investigated
and they might contain useful info, for example a starting
altitude for rides that have no location info.
Other changes:
Fix numerical stability around zero in blinn and quadratic
solvers. Improve quadratic solver accuracy.
Fix issues with computing gradient from non-uniform
cubic splines.
RideFiles now record additional altitude accuracy.
Basics now in place to plot line, scatter, pie and bar
charts. This commit finishes off the final bit of part
2, adding axes control.
A new GC api, GC.setAxis(..) has been added allowing
fine grained control on the axes added automatically.
They reference axes by name, based upon the xaxis and yaxis
parameters passed to the GC.setCurve(..) function.
GC.setAxis(..) should be called /after/ the curves are
added since it will not create axes in advance.
Fixes a copy/pase problem preventing workout import via Drag and Drop
and allows to import GPX files as workouts or activities according to
active view.
Fixes#3337
Added Pie and Bar charts with some rudimentary axes
being created automatically.
Need to follow up with mechanism to work with axes from
within the python script, likely needs a new binding.
Updating the python chart to render via a Qt Chart in addition
to the existing web page rendering.
Five aspects are planned:
1. Add QT chart option, basic rendering of Line+Scatter (this commit)
2. Add legend and axes, support for Pie and Bar charts
3. Add interactivity / hover etc
4. Add options for annotations and markers
5. Add more advanced charts and chart objects
There is an example in the tests folder, but at this point the
chart is very basic, but the main plumbing is in place.
Add support for a generic set of VO2 measurements:
* Respiratory Frequency
* Respiratory Minute Volume aka Ventilation
* Volume O2 consumed
* Volume CO2 produced
* Tidal Volume
* FeO2 (Fraction of O2 expired)
* Respiratory Exchange Rate (calculated as VCO2/VO2)
Make the new metrics usable in TrainView, and store VO2 data as XDATA
using the same pattern as for HRV data.
Add support for VM Pro by VO2Masters
The VM Pro is a BLE device, so support is added in the BT40Device class.
Since the device requires some configuration in order to be usable, such
as the size of the "User Piece" a special configuration widget is added
and shown in a separate window when the device is connected.
This window is also used to set a number of useful settings in the
device, and to show calibration progress. There's also a detailed log of
the status messages shown, and this can also be saved to file.
Allow notifications from RealtimeControllers and devices in the
notification area of Train View. In order for devices to display
information in the notification field in TrainBottom the signals need
to added and propagated from from device level via RealtimeController
to TrainSidebar and finally TrainBottom.
Fix an issue with multiple BT40Device per actual device
Currently on MacOS there will be multiple BT40Device per actual device,
since the QBluetoothDeviceDiscoveryAgent::deviceDiscovered() signal is
emitted multiple times with e.g. updated RSSI values. Avoid this by
checking the previously created devices first.
MacOS doesn't disclose the address, so QBluetoothDeviceInfo::address()
can't be used there, instead deviceUuid() is used which is instead only
valid on MacOS.
* FitRideFile: handle single values in decodeHRV()
Currently only records of type ListValue are handled, but single
RR-intervals can also come as type SingleValue. Before such records
were silently ignored.
* FitRideFile: Unify indentation of decodeHRV()
The indentation before was a mix of tabs and spaces, which made the code
quite a challenge to read. This unifies to use 4 spaces at least
throughout the function.
* Added test file
Fixes#3297
.. when a new athlete is created and opened the blankstate page
currently provides options to get data by importing files or
downloading from a device.
.. this update adds the ability to configure a cloud service and
start a sync straight away
.. this UX is introduced since cloud services are now much
more ubiquitous and v3.5 introduced broad support for a wide
range of services.
.. the authorise button on the add cloud wizard now
shows a 'Connect with Strava' icon
.. all other services continue to have a button that
is labelled 'Authorise'
.. this is needed to comply with the Strava API application
guidelines.
.. when data is downloaded from strava we now set the metadata
tag "StravaID" to the id of the activity on Strava.
.. On RideSummary a link is added at the bottom to view the activity
on Strava if the "StravaID" is set.
.. if the user clicks on the link the summary is replaced with the
strava page for the ride:
e.g. https://www.strava.com/activities/962515512
.. this is part of a couple of updates to comply with the Strava
guidelines for consumption of the Strava v3 API, see:
https://developers.strava.com/guidelines/
Some older (Tacx) RLVs do not have a sync point at the end of the course.
This work-around calculates the total distance of the course and sets a final sync point
if one does not already exist.
Revised code in VideoSyncFile::parseTacx to build syncpoint list with correct distances
when speed varies between two points
Revised code in VideoWindow::telemetryUpdate to interpolate position between 2 sync points.
Also do not update video if paused or not running.
Revised code in VideoWindow::startPlayback to set a minimal rate to start if video is
controlled by syncfile. This avoids the initial "rush" that otherwise happened and
makes for a smoother start.
Also reset distance to 0 on start.
As the rlv length now more accurately matches the workout length, we also need a check in
TrainSidebar::guiUpdate that will terminate the workout if the end of the video is reached.
This code has problems when distance is used on x-axis (#2842)
and it is redundant since there is a general mechanism to plot
any XData series as User Data in Activitiy chart.
This reverts commit f095416c5c.
* Initial implementation of Python data processors
* Add RideEditor to PyFIx script editor
* Enable write-access to activity data for python fixes
* Add GC.deleteActivitySample method
* Add GC.deleteSeries method
* Check for python fix for changes before close
* Build python fixes menu dynamically
* Make python fixes first class data processors
* Add GC.postProcess method
* Check GC_WANT_PYTHON and "Enable Python" setting for python fixes
* Add GC.createXDataSeries method
* Clean up ScriptContext ctor mess
* Support editing xdata series
* PDP: Implement xdata append/remove methods
the website appears to expect UTF8 by default, so let's send a UTF8
title (plus an explicit header)
tokens and boundaries are supposed to be ASCII, so they can keep their
latin1 encoding
GPSMap 66 can use ANT+ sensors, store in FIT format, synchronization with Garmin Connect and relevant to use with long-term activities (walk/hiking/ski).
Implement regex/hash based string substitution object to perform multiple
substitutions in 2 passes. Speeds up athlete data load by 2x.
Use QStringRef to avoid copy
Fixes#3234
Currently Device does not work on filters and set/unset/isset fail silently,
with this change Device can be used in filters as standard metadata and
the attempt to use in set/unset/isset reports an appropriate error.
We could enable these operations in the future but they require special casing.
To allow user testing, similar to linux builds.
Includes some minor fixes:
-Avoid compiler warnings for deprecated declarations to reduce the log size
-Patch GoldenCheetah.dmg to include missing libicudata.64.dylib
-fix command line error in mackdeployqt -fs option
If video config file is not present copy a default one to be used as a model
by the user. An empty video-layout.xml file disables video overlays
Fixes#2525
AddPairBTLE depends on the presence of an ANT+ dongle and sensors
to support ANT+ for detection, it looks like a copy paste of AddPair.
This works for Dual (ANT+/BTLE) sensors with an ANT+ dongle since
the sensors are detected, although is misleading since it seems to
imply you can pair them selectively, which is not true for current
BT40 GC implementation.
When an ANT+ dongle is not present (see #2771) or the sensors only
support BTLE (see #2983), the wizzard informs no sensor is dectected.
This is misleading since BT40device will dectect and use automatically
any Hr/Power/CSC sensor present at device startup.
This change replaces AddPairBTLE code with a simpler version matching
current BT40 support: it just informs the user the sensor types supported
indicating they will be autodetected on device startup.
Fixes#2771Fixes#2983
* Enable import of XDATA series from CSV files
Since XDATA series are preserved across merges this allows to add
arbitrary XDATA series to any activity.
Sample WEATHER file is included for testing.
Sample swim file is also included, once imported set Sport=Swim and use
Fix Lap Swim with pool length=25 to rebuild standard series and laps
Fixes#2010 item 4.
* FixLapSwim - Alternative way to store pauses in XData
Some devices s.t. Moov Now generates a CSV with REST field
after each length. FixLapSwim now can use this alternative
way to express pauses and to mark end of laps.
This is intended to be used together with XDATA csv import.
A Moov Now csv file modified to comply with our format is
added as an example to test folder.
* Allow Banister to use other performance metric besides Power Index
Performance metric can be selected from any Peak metric in LTM Charts
Datafilter now is banister(load_metric, perf_metric, ...)
* Travis-ci - R3.6 install update key
According to https://cloud.r-project.org/bin/linux/ubuntu/README
We need to save the calendar type for older CalDAV code to work,
additionally Google calendar needs the calendar ID (tipically the same
as the email address), used the optional Key setting field for this.
- When there is no power don't add (0w)
- Move the rounding to the format method to avoid Pace issues (Fixes#3106)
- Pending: make the rounding dependent on the series.
This solves the issue when activities not having all the data
channels available are aggregated.
Forces a metric recomputation to account for these changes.
Since counts are relevant for averaging them between different rides.
Required to fix the issues when aggregating Time in Zones Percentages.
The previous solution worked until you exit GC since when the RideDB
was reloaded the counts with zero values were lost.
So it aggregate properly in Metric Trends Charts, currently
when one of the rides to be aggregated has 0 percent in one of
the zones the aggregate is distorted and it can be higher than 100%
which is particularly notable when the bars are stacked.
This has been reported several times at the forum.
As for the L/R balance (see https://github.com/GoldenCheetah/GoldenCheetah/pull/3098) there are issues in the Torque Effectiveness and Pedal Smoothness computation when using Favero Assioma DUO pedals. In some cases, values for LTE, RTE, LPS, and/or RPS are stored in the file while the power and/or cadence data shows that the correspondent stroke was either void or no power generating (see the attached image in https://github.com/GoldenCheetah/GoldenCheetah/issues/3102). This was not taken into account in the code, as the only check was the existence of LTE, RTE, LPS, and RPS data greater than zero. I've made the necessary changes in order to check if the stroke was a power generator by verifying if the cadence, power and lrbalance values are valid (it is SUPPOSED that all files that contain LTE, RTE, LPS, and /or RPS contain also power, cadence, and lrbalance data, as they are necessary for the LTE, RTE, LPS, and RPS values computation)
Fixes#2745 which requests this metric plus it allows to fix the issue with
Time in Zone Percentages which don't add to 100% nor aggregate properly
when there are gaps in recording, tipically due to pauses.
When there are no gaps Time Recording equals Duration and Time in Zone
Percentages don't change.
The user is requesting explicitly the length expansion so, to avoid
confusion, we should ignore this setting, which was badly handled
to make things worse.
Fixes#2892
Change in order to manage correctly the Left/Right balance due to the issues detected with the Favero Assioma DUO pedals, as it was explained here: https://github.com/GoldenCheetah/GoldenCheetah/issues/2955
But after I detected the issue, this file was modified in order to accomplish the proportion of Ground Contact Time from each leg for runs, and a new check was added to the code (point->cad || point->rcad), while in the original code only the point->cad was tested. I'm not sure if the addition of my new checks, specially the (point->watts > 0.0f) one, are safe for the running part of the function
- Performances are computed independently for Rides and Runs in Estimator
- Running Performances are shown in LTM Charts When all selected activities
are runs for a Performance curve
- Banister models uses Performances from activities were score > 0
and for the same date with matching sport, so a Banister model based
on BikeScore/BikeStress will include only rides while one based on
GOVSS will include only runs
- Banister (Run) chart based on GOVSS metric added for testing
- PDEstimate now has a run flag, Estimator has 2 passes: rides and runs
MultiModel and WSModel are disabled for the same reason they were disabled
in CP chart, and to lower the performance impact.
- Show CP Models Estimates for Running in RideSummary when the involved
activities are all runs.
- DataFilter estimate function uses Bike or Run models based on activity type
- Metrics Trends charts Estimate allow Bike vs Run selection
Another attempt to minimize the use of issue tracker as a help desk.
Additionally we could use the new templates feature for bugs and features, but I don't have permissions to change repository settings.
-Extra data fields renamed and scaled according to spec: stance_time_percent,
activity_type, vertical_ratio and step_length
-Average metrics for the new fields: Average Stance Time Percent,
Average Vertical Ratio and Average Step Length
-Tested using Garmin 935 with Running Dynamics Pod
.. UserData series now have a zone string that
can be used to define upper values and associated
colors for shading a curve.
.. the format is: lim,colorname;lim,colorname;
where lim is an upper value and colorname is
either a #rgb string or any color name such
as red,green, blue etc from the list of SVG
color keyword names provided by the World Wide
Web Consortium.
e.g: 200,green;300,yellow;9999,red
which will shade points <200 green, <300 will be
yellow and then <9999 will be red.
The zones must be listed in ascending order.
.. there are too many incompatibilities between the
V3 license and other codebases we wish to work with
that are based upon the GPL-V2 license.
.. this downgrade is to ensure we are compatible and
can align with contributions from other parties in
the future.
.. a notification will be sent to the mailing list to
inform all users.
.. updated the QwtPlotCurve to fill using zones.
.. next commit to update user data curves in AllPlot
to let the user set zones and colors.
.. added as part of updates for Humon collaboration.
... with windows / VC2017 / 64Bit the code does not build / cannot resolve a overwritten function when using QT 5.12.1
... adding the newly introduced function similar to the other function resolves the compile problem
.. ErgFile now supports gpx format as well as .erg,.mrc et al
.. Location data is include in realtime data and passed through
.. the CSV file format has been fixed to record GPS with higher precision
Fixes#3021Fixes#3024
.. code originally developed by Eric Christoffersen
for merging data from virtual rides where distance is
recorded on a trainer, so the GPS and altitude data
can be merged in to the data.
Even when it is considered not relevant for runs and swims the metric
code computes the value if power data is present which may produce
unwanted results as reported at the users forum.
.. banister(metric, nte|pte|perf|cp)
so you can filter rides where predicted cp is over
300 with "banister(BikeScore, cp) > 300".
.. of course the real value is being able to access
banister data in metrics and formulas.
.. don't show helper in data table or compare mode.
.. always extend out banister date range to at least
a year from the current date. To make sure the
decay is calculated well into the future.
.. split if no gaps in seasons and combine if seasons
are too short.
.. this way we get fairly stable fits (2yr window size)
but also get to see parameters reflect aging, so
p0 declines and k1/k2 fit better.
.. still need to think how t1/t2 should adjust...
.. can refit to see affect of adjusting parameters.
.. doesn't "remember" them, need to think about what
that should mean (config in chart, season or athlete?)
.. also made t1/t2 fixed in the fit process so we have
fewer parameters and need less data to fit.
.. added a banister helper like on the CP plot
.. you can't adjust T1 and T2 yet, thats coming
in the next commit
.. also a few fixups related to submax filtering
of performances and some wip regarding how
the model fit works (windows, t1+t2 fixed etc).
.. Banister implementation is still under some
development, testing and validation but is in
good enough shape to try with your data.
.. we only have banister curves where there is data
so if there are gaps between seasons we should not
plot any data.
.. as a result also fixed bug that the qwt gapped
curve would always plot first zero in a curve.
.. Banister model fitting using LM
.. can plot Banister curves on trends plots;
- Performance curve (NTE+PTE)
- Predicted CP curve (Performance curve scaled)
- Negative Training Effect
- Positive Training Effect
.. the code is sub-optimal and needs to be refactored
to cache and refresh less frequently (using the same
pattern as PMC most likely).
.. the model fitting can fail and needs to be made a
lot more robust, along with ensuring the samples
we fit to are appropriate.
.. filter out submax performances
.. plot performances on LTMplot;
* tests - marked as TTEs by user
* weekly performances - found by algorithm
* submaximal performances - filtered out by algorithm
.. we now have the neccessary data to introduce the
Banister NTE/PTE and Performance curves in the next commit.
.. show weekly best performances (ready for banister curves)
.. show performance tests (also used by banister if present)
.. can toggle which ones to show.
.. use powerIndex to select points when t > 120s. This has resulted
in a much higher hit rate at finding performance tests in MMP
data (almost 99% of the time).
.. As part of a series of commits to add Banister IR modeling
this first one introduces a Power Index metric that can be
used to normalise TTEs of a different duration to a single
score.
.. This is so we can use performance tests of differing durations
when fitting Banister model curves to estimate k1 and k2.
.. The average power for an interval/ride is compared directly
with a power estimate for the same duration using the Morton
3-parameter model and mean values derived using opendata (where
CP=261, W'=15.5kJ and Pmax=1100w)
.. For the equivalence to be valid test must be in the 2-20 minute
range when used in banister modeling, but the index value is
valid as a comparison to the average athlete for all durations.
.. add option to apply a decay factor to CP and W' when plotting
the model curve in CP Plot.
.. since we always fit to observations <20mins the mostly submax
points at longer durations in the general population do not
impact the fit at all.
.. the decay factors for w' and cp have been fit to the results of:
Effects of Two Hours of Heavy-Intensity Exercise on the Power-
Duration Relationship
Clark IE, Vanhatalo A, Bailey SJ, Wylie LJ, Kirby BS, Wilkins BW,
Jones AM.
https://europepmc.org/abstract/med/29521722
Existing code for OSX was migrated to scripts on travis/osx without changes.
New scrtps for Linux were added to travis/linux based on previous work
by gcoco and LyzardKing
Install linux dependencies similar to OSX version, including samplerate,
vlc, ical, kml, d2xx, srmio, libusb-compat/libusb1.0 and R 3.5
Enable CloudDB and Cloud services using shared secrets with OSX version
Generate AppImage and set src/$FINAL_NAME to enable automatic deploy
Optionally upload the AppImage to transfer.sh for testing
* train: add support for serial daum devices
Add support for daum devices connected via serial port.
Such device could be:
- Daum Vital
- Daum ergo_bike series
* ergo_bike_2002
* ergo_bike 4004 TRS
* ergo_bike cardio
* ergo_bike vita
* ergo_bike fitness
The only device I own is a Daum Vital, therfore this is the only device
that is known to work correctly.
The default behaviour is to send the load to the device only once to
allow the user to interact with the device. The profile field is used
to pass a _force_ flag in form of a string containing the word _force_.
Doing so will cause the implementation to send the load to the device
every _poll interval_ (default 1s), except the training is paused.
Signed-off-by: Florian Nairz <nairz.florian@gmail.com>
* train: daum: fix unsigned/signed compare mismatch and add return value
.. using analysis from the opendata proejct we have now
got a normal distribution for CP, W' and Pmax parameters.
.. so we can now plot the percentiles on the CP plot that the
user's values sit in.
An explainer from Robert Chung for a regression method to estimate CdA and Crr from field data.
The key point being the generation of additional laps from a multi-lap run -- e.g. 3 x 18s laps of a velodrome
would normally be considered as 3 laps to fit against. Robert's approach is to create 36 laps from this data (!).
The first lap starts at 0s and lasts for 18s, the second lap at 1s ... up to the 36th lap starting at 37s.
We would then be able to get 36 estimates of Crr/CdA and calculate a mean and confidence interval (!).
The document committed explains how that regression would work mathematically, and how we
would adapt for working in the field (we need really good altitude data).
.. reads .rr file when processing csv and adds the XDATA
series "HRV".
NOTE: the HRV processing data added by Leif Warland will
process the data and calculate SDANN/SDNN and friends
since we use the same convention as for Polar HRV.
.. record hrv R-R data to .rr file in the "records" folder when
R-R data is available in train view.
.. next commit needs to read it in and save to XDATA
.. collect R-R data from ANT+ devices and deliver to
the train sidebar.
.. commit 2 needs to save to a file when recording a
workout in train view
.. commit 3 needs to import the R-R data into XDATA when
importing a train view CSV file
.. mousepad touch events require focus, so we disable
touch events to stop the overview window from
stealing focus from the ride list when scrolling
through rides.
.. so you can see how the parameter estimates look when plotted
in work time.
.. this means parameter estimation and model visualisation are
separated -- you can estimate CP/W' using the extended model
and an envelope fit but visualise with the linear work model.
.. add fitting option to fit CP2 model to points using
a linear regress.
.. kinda ironic that the most common and straight forward
method for estimating CP/W' is added so late.
.. when model changes set the fit type to the best practice
we would recommend with that model (and in the case of
multimodels disable unsupported fits)
* CP2/CP3 - LMA and Performance Tests
* Extednded CP - Envelope and all MMP
.. change the default intervals within the models - these
are used when estimating automatically via envelope and
were too long.
.. truncated the data used by the models to avoid using
MMP data beyond 20 minutes for 2/3p model.
.. results in much more robust estimates in CP History.
.. allows constrained fits
.. this is a GPL lib that is included into the
source tree to avoid adding another painful
deendency.
.. for details of the lib please see:
http://users.ics.forth.gr/~lourakis/levmar/
.. returns the number of performance test intervals for the ride.
.. can be used to filter for only rides with tests, or even multiple
tests in the same ride (e.g. 3,7,12 tests).
.. may add additional paramaters later to e.g. filter by duration or
average power etc.
.. honour interval color selected by user when plotting
performance tests on the CP plot
.. performance test symbol size is enlarged if the test is
within the currently selected ride (in activity view).
.. right click options to
* mark a user interval as a performance test
* create a performance test interval from a disovered interval
.. this way when interval discovery finds a hard effort that you
want to clone as a performance test, you can do it with one
click.
.. CP plot modelling will fallback when insufficient data
is available to model reliably, with a precedence:
1. Performance tests
2. Filtered MMP
3. All MMP
.. when modelling for a single ride collect bests/performance
data for the period up to that ride.
This is so as you select older rides the model reflects the
training status at that ride, not for the current period.
.. add adhoc season for 'Last 6 weeks' since it is a common
timeframe to use when tracking impact of training
.. tell user what fit or data was used as there is a cascade back
depending on the model selected and the availability of data.
.. the summary is also now in grey to indicate it is supplementary.
.. RMSE for now, just to get a basic sense
.. what type of fit was performed (since there is a fallback)
.. how many datapoints were used in the fit and RMSE calculation.
.. add option to CP chart to fit model to marked performances.
.. works, but very crude UI - no warnings if not enough data and
no constraints on combinations of model, fit and fit data that
can be selected.
.. will tidy up over the next few days.
.. as a first pass lets show the performance tests on the CP
plot to get a sense of how any bests / models align to the
results of our tests
.. we will look to fit to the tests using LMA in another commit.
.. editing a user interval color never worked properly.
the color wasn't changed or remembered at all.
.. lots of independent bugs conspired to cause this but
mostly it was because the interval color was not
recorded in the ride file.
NOTE: files created with this release will not be
backwards compatible with earlier releases.
.. allow the user to set a flag "Performance Test" against an interval
within an activity.
.. the distinction is needed to highlight the section of an activity
that was a test (as opposed to the entire activity containing
test efforts.
.. this is so we can fit them to PD and IR models in the future
avoiding the need to use algorithms to extract TTE type efforts.
.. the update was surprisingly complex since we need to update the
ridefile to record this with the interval and also update the
ride cache as well as adding the bool to all the interval helper
functions.
.. along the way it became clear why user specified colors for
intervals were getting lost (they are not in the ridefile) and
will fix this in another post.
.. NOTE: ridefiles created with this version will not be backward
compatible with earlier versions because they contain a
new field for intervals marked as performance tests.
Access SpecialFields::isMetric() via context->specialFields
Avoids duplication and fixes#2894 since the context->specialFields
is updated in RideCache when user metrics definitions are loaded.
.. its dead (not updated for 5 years)
.. it introduces dependency issues with openssl/crypto/icu
on Linux distros
.. we don't need it, since OAuthDialog does the heavy
lifting we need (ok, its not pretty but it works).
.. old code moved into the deprecated folder
Fixes#2881
.. the code to parse the redirect url and exract
the query item 'code' was fragile -- and got
broken when Strava added a new query item to
the returned URL.
.. we now use QUrlQuery to extract in a more
robust and future proof way
Fixes#2879
* fix unclosed file descriptors
* remove various compiler warnings
sometimes it was only ambiguous indentation, sometimes bugs were fixed:
- forgotten `break;` instructions or `fallthrough` annotations:
- src/ANT/ANTChannel.cpp
- src/Charts/CriticalPowerWindow.cpp
- src/Charts/MUPlot.cpp
- src/Core/DataFilter.cpp
- src/FileIO/RideFileCache.cpp
- src/FileIO/RideFileCommand.cpp
- src/Train/DialWindow.cpp
- forgotten braces:
- lmfit/lmmin.c
- src/FileIO/XDataDialog.cpp
- test on the wrong variables:
- src/Gui/Pages.cpp
- wrong parenthesis
- src/Charts/CPPlot.cpp
- missing macro argument
- src/Cloud/WithingsDownload.cpp
- missing `return;` statement
- src/Cloud/Xert.cpp
- unused variables
- src/Gui/DiarySidebar.cpp
- unclear indentation
- src/Core/RideItem.cpp
- src/FileIO/BinRideFile.cpp
- src/Metrics/PaceZones.cpp
- src/Metrics/RideMetadata.cpp
- src/Metrics/Zones.cpp
* remove unnecessary Leaf::Parameters enum value from data filters
lists of parameters don't exist as such outside of the parser, and have
no business using the same type `Leaf` as complete terms anyway
* remove unnecessary argument
`leaf1.print(leaf2,...)` would print `leaf2` and completely ignore
`leaf1`, so now `leaf2.print(...)` is used instead
.. when looking for efforts in a workout that are at or
above the limit of the athlete we stopped as soon as
we found a section that was too hard.
.. we now keep looking for impossible sections since there
are often multiple hard efforts hidden within a longer
section.
.. there does not seem to be any considerable performance
overhead with this approach.
.. when warning if sections of a workout TTE is longer
than athlete ability use the 3-param model not the 2
param model.
.. this will check intervals shorter than 2 mins.
.. was supposed to do this originally, but got lost in
other fixups and development.
.. makes compilation easier and removes a dependency
for what is effectively 2 C-source files.
.. additionally, getting the lmfit lib to compile
on windows with cmake was frought with issues.
.. also fix a debug message left behind by previous
commit.
.. adding an option to select least squares fit to the cp
chart, in addition to the existing envelope fit.
.. additionally, if filter bests option has been selected
the least squares fit will use these points rather than
all the points (since well over 95% will be submaximal).
.. It requires the lmfit library to be available - and this
has been an non-optional install for over a year - we
just haven't used it prior to this commit.
.. Each PD model needs to implement three functions to enable
the least squares fit to work:
* int nparms() - returns the number of parameters
* double f(double t, double *parms) - parametric function
* bool setParms(double *parms) - set the parameters post fit
.. This commit implements it for CP derivatives;
* Classic CP - 2 parameter model
* Morton 3 Parameter - 3 parameter model
* GC Extended CP model - the extended model
BUT: it is implemented and disabled for eCP for now until
we can set parameter constraints correctly.
.. A second commit is needed for the remaining models from
Ward Smith and Mike P. This should also show which of the
filtered points have been used for curve fitting on the
chart (maybe a different color)
xdataNames, xdataSeries and xdata refer to low level functions
activityXdata is a wrapper to obtain XData series by name without interpolation
activity includes all XData series interpolated
When name="" returns a list of XData series names present
When name is an XData series present return a dataframe with vectors for:
time, distance and each valuename
with a row for each XData sample.
Implements #2847
When name="" it returns XData names
When name is one of the names for the activity it returns valuenames
To dinamically obtain names/series for activityXdata and activityXdataSeries
.. if metadata is setup to use TSS, NP, IF then they
don't override the base metrics coggan_{tss,np,if}
this is because the symbol being used is for the
compatibility metrics which is one level of
abstraction away from the underlying metric.
.. instead we now handle the symbols within the
RideMetadata class, which maps TSS, NP, IF to
the coggan_tss, coggan_np and coggan_if symbols.
Fixes#2852
Even if Garmin Smart Recording is not enabled, make users life simpler
Since otherwise the datais useless and the original lenght-by-length
data is preserved as XData.
.. not checking timeIndex() for out of bounds
when secs goes negative during parsing.
.. also, enable interpolation for swim laps by
default to ensure no data loss (i.e. don't
insist on garmin smart recording setting).
Fixes#2953
New users comming from Strava, TP, etc. expect this behavior by default
This doesn't affect single sport metrics, only the global score.
TRIMP Zonal Points are a reazonable proxy and they are configurable
via trimp-k coefficients in HR Zones.
#### **Do you have questions about how to use GoldenCheetah?**
* Ask any question about how to use GoldenCheetah on [golden-cheetah-users mailing list](https://github.com/GoldenCheetah/GoldenCheetah/wiki), ideally after watching the corresponding [tutorials](http://www.goldencheetah.org/#section-tutorials) and/or reading the relevant parts of the [documentation](https://github.com/GoldenCheetah/GoldenCheetah/wiki).
* Ask any question about how to use GoldenCheetah on [golden-cheetah-users mailing list](https://groups.google.com/forum/#!forum/golden-cheetah-users), ideally after watching the corresponding [tutorials](https://www.goldencheetah.org/#section-tutorials) and/or reading the relevant parts of the [documentation](https://github.com/GoldenCheetah/GoldenCheetah/wiki).
#### **Do you have questions about the source code?**
Issue tracker is **only** for Bugs and Features, before to open a new issue please read the contributing guidelines (link below), and use the forums if you need help or technical support.
macOS and Linux: [](https://travis-ci.org/GoldenCheetah/GoldenCheetah)
LM_REAL*d,/* I: right hand constraints vector, k2x1 */
intk2,/* I: number of inequality constraints (i.e. C's #rows) */
intitmax,/* I: maximum number of iterations */
LM_REALopts[4],/* I: minim. options [\mu, \epsilon1, \epsilon2, \epsilon3]. Respectively the scale factor for initial \mu,
* stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2. Set to NULL for defaults to be used
*/
LM_REALinfo[LM_INFO_SZ],
/* O: information regarding the minimization. Set to NULL if don't care
* info[0]= ||e||_2 at initial p.
* info[1-4]=[ ||e||_2, ||J^T e||_inf, ||Dp||_2, mu/max[J^T J]_ii ], all computed at estimated p.
* info[5]= # iterations,
* info[6]=reason for terminating: 1 - stopped by small gradient J^T e
* 2 - stopped by small Dp
* 3 - stopped by itmax
* 4 - singular matrix. Restart from current p with increased mu
* 5 - no further error reduction is possible. Restart with increased mu
* 6 - stopped by small ||e||_2
* 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error
* info[7]= # function evaluations
* info[8]= # Jacobian evaluations
* info[9]= # linear systems solved, i.e. # attempts for reducing error
*/
LM_REAL*work,/* working memory at least LM_BLEIC_DER_WORKSZ() reals large, allocated if NULL */
LM_REAL*covar,/* O: Covariance matrix corresponding to LS solution; mxm. Set to NULL if not needed. */
void*adata)/* pointer to possibly additional data, passed uninterpreted to func & jacf.
* Set to NULL if not needed
*/
{
structLMBLEIC_DATAdata;
LM_REAL*ptr,*pext,*Aext,*bext,*covext;/* corresponding to p, A, b, covar for the full set of variables;
pext=[p, surplus], pext is mm, Aext is (k1+k2)xmm, bext (k1+k2), covext is mmxmm
*/
LM_REAL*lbext,*ubext;// corresponding to lb, ub for the full set of variables
intmm,ret,k12;
registerinti,j,ii;
registerLM_REALtmp;
LM_REALlocinfo[LM_INFO_SZ];
if(!jacf){
fprintf(stderr,RCAT("No function specified for computing the Jacobian in ",LEVMAR_BLEIC_DER)
RCAT("().\nIf no such function is available, use ",LEVMAR_BLEIC_DIF)RCAT("() rather than ",LEVMAR_BLEIC_DER)"()\n");
returnLM_ERROR;
}
if(!C||!d){
fprintf(stderr,RCAT(LCAT(LEVMAR_BLEIC_DER,"(): missing inequality constraints, use "),LEVMAR_BLEC_DER)"() in this case!\n");
returnLM_ERROR;
}
if(!A||!b)k1=0;// sanity check
mm=m+k2;
if(n<m-k1){
fprintf(stderr,LCAT(LEVMAR_BLEIC_DER,"(): cannot solve a problem with fewer measurements + equality constraints [%d + %d] than unknowns [%d]\n"),n,k1,m);
* scale factor for initial \mu, stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2 and
* the step used in difference approximation to the Jacobian. Set to NULL for defaults to be used.
* If \delta<0, the Jacobian is approximated with central differences which are more accurate
* (but slower!) compared to the forward differences employed by default.
*/
LM_REALinfo[LM_INFO_SZ],
/* O: information regarding the minimization. Set to NULL if don't care
* info[0]= ||e||_2 at initial p.
* info[1-4]=[ ||e||_2, ||J^T e||_inf, ||Dp||_2, mu/max[J^T J]_ii ], all computed at estimated p.
* info[5]= # iterations,
* info[6]=reason for terminating: 1 - stopped by small gradient J^T e
* 2 - stopped by small Dp
* 3 - stopped by itmax
* 4 - singular matrix. Restart from current p with increased mu
* 5 - no further error reduction is possible. Restart with increased mu
* 6 - stopped by small ||e||_2
* 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error
* info[7]= # function evaluations
* info[8]= # Jacobian evaluations
* info[9]= # linear systems solved, i.e. # attempts for reducing error
*/
LM_REAL*work,/* working memory at least LM_BLEIC_DIF_WORKSZ() reals large, allocated if NULL */
LM_REAL*covar,/* O: Covariance matrix corresponding to LS solution; mxm. Set to NULL if not needed. */
void*adata)/* pointer to possibly additional data, passed uninterpreted to func.
* Set to NULL if not needed
*/
{
structLMBLEIC_DATAdata;
LM_REAL*ptr,*pext,*Aext,*bext,*covext;/* corresponding to p, A, b, covar for the full set of variables;
pext=[p, surplus], pext is mm, Aext is (k1+k2)xmm, bext (k1+k2), covext is mmxmm
*/
LM_REAL*lbext,*ubext;// corresponding to lb, ub for the full set of variables
intmm,ret,k12;
registerinti,j,ii;
registerLM_REALtmp;
LM_REALlocinfo[LM_INFO_SZ];
if(!C||!d){
fprintf(stderr,RCAT(LCAT(LEVMAR_BLEIC_DIF,"(): missing inequality constraints, use "),LEVMAR_BLEC_DIF)"() in this case!\n");
returnLM_ERROR;
}
if(!A||!b)k1=0;// sanity check
mm=m+k2;
if(n<m-k1){
fprintf(stderr,LCAT(LEVMAR_BLEIC_DIF,"(): cannot solve a problem with fewer measurements + equality constraints [%d + %d] than unknowns [%d]\n"),n,k1,m);
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.