Compare commits

..

828 Commits

Author SHA1 Message Date
Mark Liversedge
5c84f7f789 VERSION 3.6 DEVELOPMENT JUNE 2020
.. update build id prior to tag.

[publish binaries]
2020-06-14 18:56:18 +01:00
Mark Liversedge
dbecc005b5 Overview Chart on Trends view
.. 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).
2020-06-14 17:48:17 +01:00
Ale Martinez
04b4d945fa FitRideFile - Don't call splitSessions without rideFile
To avoid crashes and since there is nothing to do.
2020-06-13 10:53:35 -03:00
Ale Martinez
74f3a213ac Don't try to split FIT files with errors
Fixes #3479
2020-06-12 19:17:39 -03:00
Ale Martinez
f3af493aba Enable Qt 5.15.0 for macOS Travis-ci builds
[skip appveyor]
Also upgrade Python to 3.7.7
2020-06-12 14:38:17 -03:00
Ale Martinez
f6bcccb04c Require Qt >= 5.13 to build v3.6
No need for conditional compilation for previous versions.
Added message at build time to avoid confusion.
2020-06-12 14:29:50 -03:00
Ale Martinez
c1727623a8 Recognize Polar S625x srd files
Add 2 test files from S625X
Fixes #3489
2020-06-12 13:07:37 -03:00
Ale Martinez
757a01e876 Add Garmin MTB Dynamics to FitRideFile
Grit and Flow - Fixes #3488
2020-06-12 11:34:06 -03:00
Michel Dagenais
20d8836708 Add user notification for bluetooth devices and services connected 2020-06-11 19:56:03 -03:00
Michel Dagenais
775765b853 Insure computation accuracy for speed and cadence
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.
2020-06-11 19:56:03 -03:00
Michel Dagenais
3982267e29 Add support for the Wahoo Kirck (Core) through BlueTooth LE
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.
2020-06-11 19:56:03 -03:00
Ale Martinez
fc4b8f7cbc Update minimum Qt version to build v3.6
[skip ci]
2020-06-11 17:27:04 -03:00
Ale Martinez
7274268f47 Suppress deprecation warnings - will be fixed with Qwt 6.2 2020-06-11 15:10:41 -03:00
Ale Martinez
e1f9005cf5 Fix Qwt incompatibilities with Qt 5.15.0 2020-06-11 12:54:29 -03:00
Ale Martinez
16e00fde90 macOS Travis-ci builds - fallback Qt and Python versions
[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
2020-06-11 00:23:12 -03:00
Michel Dagenais
2418d3b95b Convert size from pixels to points for use in setPointSize (#3452)
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.
2020-06-10 22:24:53 +01:00
Mark Liversedge
df2d436a02 User, R and Python Chart fill curves
.. add ability to plot filled curves.
2020-06-10 19:59:21 +01:00
Ale Martinez
20c975e7df Don't call locationAt/gradientAt in Erg mode
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 1402f6ad6a
Fixes #3491
2020-06-10 14:24:04 -03:00
Ale Martinez
7d8c27fd54 Initialize mode when parsing Erg2 workout files
Otherwise they can inherit the wrong mode from previous workout
2020-06-10 11:53:10 -03:00
Ale Martinez
b0a8c6edfa Add units to Load source for overlay widgets 2020-06-10 11:43:29 -03:00
Mark Liversedge
6163ece7d6 KPIOverviewItem painting nit
.. setData() was adjusting visibility of the progressbar and should not
   have been. Now calls itemGeometryChanged() to manage that correctly.
2020-06-10 09:54:40 +01:00
Mark Liversedge
66fb3b2bde Overview nits
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.
2020-06-09 21:17:33 +01:00
Ale Martinez
14e6fd5393 Add VideoOverlays capture for the wiki
[skip ci]
2020-06-09 16:01:00 -03:00
Mark Liversedge
47d79bd872 KPI overview item
.. 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)); }
2020-06-09 19:45:44 +01:00
Mark Liversedge
6e8bad3d19 Fix Overview Zone settings
.. data loss by updating during initialisation of config widget.
2020-06-09 08:50:00 +01:00
Ale Martinez
1ec634f043 Replace modal dialog with emit setNotification in Computrainer Controller
The "Cannot Connect to Computrainer" now shows in TrainBottom notification
area unobtrusively. Fixes #2439
2020-06-08 20:03:13 -03:00
Mark Liversedge
2b54f68d50 Overview Config Part 2 of 2
.. 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]
2020-06-08 21:17:19 +01:00
Mark Liversedge
410aaf6a93 Overview Config Part 1 of 2
.. '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.
2020-06-08 17:13:55 +01:00
Ale Martinez
60600948be Add Tacx NEO 2 Smart
Fixes #3484
2020-06-08 11:34:10 -03:00
Ale Martinez
3450f577d3 Add Garmin HRM-Dual
Fixes #3483
2020-06-08 11:31:54 -03:00
ericchristoffersen
d55cd20639 Elevation Widget: Lazy Init Polygon to Avoid 2x Route Point Iteration (#3477) 2020-06-07 12:55:24 -03:00
Mark Liversedge
56ecb3e538 Add Overview with default config
.. 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
2020-06-06 11:05:34 +01:00
Alejandro Martinez
365848b79e On Windows attach to parent's console when no console is available
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]
2020-06-05 17:59:33 -03:00
Mark Liversedge
125a92514c Fix ChartBar Remove Chart SEGV
.. 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.
2020-06-05 10:05:33 +01:00
Ale Martinez
0881250542 AppVeyor - Change python._pth encoding
utf8 generates a BOM which Python doesn't like
lib/site-packages is included in path by include site
[skip travis]
2020-06-04 15:57:41 -03:00
Mark Liversedge
0286583d4b Fix UserChart series de-dedup when editing
.. 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.
2020-06-04 08:11:19 +01:00
Mark Liversedge
7cc6733df1 Fix userchart duplicate series name SEGV
.. 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.
2020-06-03 21:47:45 +01:00
Mark Liversedge
4447f8bffd Fix SearchBox size regression
.. 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.
2020-06-03 21:16:33 +01:00
Mark Liversedge
ddcd2825a2 LTM and CP chart menu override
.. 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.
2020-06-03 20:45:20 +01:00
Ale Martinez
f24ee9be8a Reduce mimimum height of Python Fix Edit dialog
To fit in high-dpi laptops displays without too small font
2020-06-03 15:22:16 -03:00
Ale Martinez
5194d09ec3 BT40Device - Fix Ignoring the CSC service for device xxx message
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
2020-06-03 13:54:40 -03:00
Ale Martinez
bc13092cd2 Python Fixes - Clear context before to execute the script
Fixes #3459
2020-06-03 13:37:38 -03:00
Ale Martinez
15b491409a Fix AppVeyor deploy to S3
[skip ci]
It was uploading to S3 on every push to master.
2020-06-02 18:55:02 -03:00
Ale Martinez
92f3a237be Trim Python Home setting
If it contains blanks deployed Python detection fails,
lets make this a little more idiot-proof.
2020-06-02 18:44:07 -03:00
Mark Liversedge
a6ed25c7e4 Overview refactors cosmetic nits
.. spacing and margins got doubled and tripled up in layouts and
   some other related minor fixups.
2020-06-02 21:57:59 +01:00
Mark Liversedge
45a628b4b9 ChartBar context menu in Tab
.. 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).
2020-06-02 20:41:28 +01:00
Michel Dagenais
b6ee709520 Fix incorrect speed (halved) on BT40 (#3456)
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,
2020-06-02 10:35:46 -03:00
Adrien Guinet
77bbca0a16 ErgFile: fix distance precision issues (#3435)
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").
2020-06-01 20:53:53 -03:00
Adrien Guinet
6ca1bd9a9c BT40: add support for Tacx's ANT over BLE (#3430)
This is based on https://github.com/abellono/tacx-ios-bluetooth-example/
This has only been tested so far with a Tacx Flow Smart T2240.
2020-06-01 20:51:01 -03:00
ericchristoffersen
93ff6c36b4 FixGPS - Dont Stomp Slope (#3468)
Rely on invalidate.
Fixes #3466
2020-06-01 11:57:20 -03:00
Ale Martinez
6a3734971d Add information about GSL as a mandatory dependency
[skip ci]
2020-05-31 19:35:47 -03:00
Mark Liversedge
f8f43eed4c Fir set RPE from Overview Regression
.. updating the RPE value via the RPE widget on the overview was lost in
   the last commit, this fix reinstates it.
2020-05-31 18:55:36 +01:00
Mark Liversedge
8a1842a9ba Refactor OverviewWindow for ChartSpace
.. 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.
2020-05-31 18:16:53 +01:00
Ale Martinez
2d3eed0a98 Cleanup non-optional Defines from CI config
Removed redundant config and fixed GSL for windows instructions
Remove some compiler warnings to reduce log size
2020-05-30 18:13:20 -03:00
Ale Martinez
df160a10a1 Strava Download - Prevent laps overlapping and fix Lap Swim distance
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.
2020-05-30 16:55:25 -03:00
Mark Liversedge
a8473441ae GNU Scientific Library (GSL) Mandatory Dependency
.. making GSL mandatory, so we can rely on the modelling functions
   being available, amongst a few other things.

[publish binaries]
2020-05-29 15:51:58 +01:00
Ale Martinez
f18b5470ec Create Overlay Widgets with Qt::Tool flag on Linux
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.
2020-05-27 18:04:41 -03:00
Alejandro Martinez
f51a6a6cb1 Remove Conditional Compilation for Qt < 5.9 (#3464)
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.
2020-05-27 09:26:25 -03:00
Mark Liversedge
cc6fa1d02a Refresh RideFileCache before Metrics
.. since user metrics may reference the ridefile cache as part
   of the formula e.g. bests(POWER, 1200)
2020-05-26 19:54:30 +01:00
Michel Dagenais
0352e19e34 Clip the Meter Widgets to the visible portion of the Video Window (#3462)
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.
2020-05-26 14:56:11 -03:00
Mark Liversedge
4f64b88f0f Datafilter vectors - rank()
.. rank(ascend|descend, list) - returns the ranking of each element
   of list in order specified. Ranking will range from 1 to n.
2020-05-26 10:40:35 +01:00
ericchristoffersen
4348a6279c Issue 3373: FixGps to run on altitude alone. (#3374)
Fixes #3373
2020-05-25 19:03:26 -03:00
Eric Christoffersen
d52fb5a68f Fixes for interpolation and gpx file load
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.
2020-05-25 13:34:27 -03:00
Ale Martinez
c179419feb Recognise Peter Kanatselis and Michel Dagenais
By contributions to Train View code
2020-05-25 12:45:46 -03:00
Michel Dagenais
b89019264e MeterWidgets must move / hide when main window is moved / minimized (#3458)
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.
2020-05-25 12:44:54 -03:00
ericchristoffersen
922ebf987b Teach elevation widget to honor skipping (#3443)
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
2020-05-25 11:16:54 -03:00
Mark Liversedge
ca5504e486 DataFilter tests() - no submaximal
.. the recent update to tests() to retreive the bests found did not
   ignore submaximal points.
2020-05-25 12:21:01 +01:00
Mark Liversedge
369ffd2040 DataFilter vectors - estimates()
.. 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.
2020-05-25 11:29:37 +01:00
Mark Liversedge
f4fcc93693 Deprecate WebKit Support
.. The NOWEBKIT define is no longer required to build.
   We now only support building with Chromium QWebEngine
2020-05-25 09:00:36 +01:00
Michel Dagenais
e8b1f69d63 Meter widget on linux (#3454)
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.
2020-05-22 17:07:42 -03:00
Mark Liversedge
6c31805981 DataFilter vector tests() update
.. 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.
2020-05-21 19:35:17 +01:00
Ale Martinez
f2d93cc2dc Travis - Cache Homebrew downloaded bottles to speedup macOS builds
[skip appveyor]
2020-05-20 21:49:11 -03:00
Ale Martinez
5a0b022188 Travis - Enable cache for D2XX folder
[skip appveyor]
To avoid download and copy on each build
2020-05-20 21:04:35 -03:00
Ale Martinez
1cb1beb09c Enable GC_VIDEO_VLC option for macOS
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.
2020-05-20 18:39:50 -03:00
Mark Liversedge
47e67f4d37 DataFilter vectors - resample()
.. 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; }
   }
2020-05-20 14:46:57 +01:00
Mark Liversedge
5772f6fd2f DataFilter vectors - interpolate()
.. 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);
2020-05-19 18:34:38 +01:00
Ale Martinez
d4a5eaa501 Add Python 3.7 to Windows Installer and Linux AppImage
For Windows we use Python embeddable distribution
For Linux the relocatable Python AppImage
Packages included: sip, numpy, pandas, scipy, lmfit and plotly
[publish binaries]
2020-05-17 20:54:10 -03:00
Mark Liversedge
881e517b1a DataFilter vectors - random()
.. random(n) returns a vector of n random numbers between 0 and 1.
2020-05-17 18:51:43 +01:00
Mark Liversedge
21415379af DataFilter vector - samples(WBAL|WBALSECS)
.. 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.
2020-05-16 20:08:35 +01:00
Ale Martinez
89b74816f6 Travis - Add core modules to Python distribution on macOS
[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
2020-05-16 14:09:03 -03:00
Mark Liversedge
f3e9ba3573 Datafilter vectors - rev()
.. rev(vector) - returns the vector with the sequence reversed.
2020-05-15 16:51:28 +01:00
Alejandro Martinez
2b68037c72 Enable build using vlc 3 on Windows with MSVC
On Linux no changes are required
In both cases the dynamic libraries seem to be binary compatibles
2020-05-14 19:42:29 -03:00
Ale Martinez
71a81e7f01 Add sha256 hash for CI binaries to GCversionXXX.txt
[publish binaries]
2020-05-14 11:12:13 -03:00
Mark Liversedge
f261a76b9e Datafilter vectors - bin()
.. 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;
2020-05-14 12:45:11 +01:00
Ale Martinez
a94500f1c3 Add GCversionXXX.txt to CI builds results
Where XXX identify the OS, to give build context.
GoldenCheetah --version output plus the last commit.
[publish binaries]
2020-05-13 18:19:45 -03:00
Ale Martinez
2c0ce8f5c5 macOS Travis-ci build - change library path in Python interpreter
Adds SIP 4.19.8
2020-05-13 13:13:43 -03:00
Mark Liversedge
4b4d86f413 Datafilter bug fixes
.. 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).
2020-05-13 14:53:25 +01:00
Mark Liversedge
670698fdef Datafilter - quantile()
.. 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.
2020-05-11 19:39:07 +01:00
Mark Liversedge
73f11db578 Datafilter - daterange() closure
.. 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"));
2020-05-10 20:14:26 +01:00
Mark Liversedge
021ecda647 DataFilter - meanmax() set date range
.. 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; }
   }
2020-05-10 16:47:59 +01:00
Mark Liversedge
44475a03fb Datafilter - meanmax() computer
.. 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).
2020-05-10 15:57:57 +01:00
Mark Liversedge
7ee6ef43c1 Datafilter - bests()
.. 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.
2020-05-10 09:51:29 +01:00
Ale Martinez
caaae923ad Travis-ci builds - Add max-time to transfer.sh upload
To avoid the build being marked errored when the upload takes
too much time.
2020-05-09 20:07:37 -03:00
Ale Martinez
8627f26b2c Fix RideSummary Estimates
Use the the model name introduced in ed33157945
2020-05-09 19:53:22 -03:00
Mark Liversedge
f415dc38b0 Datafilter fix sum for [ selection ]
.. 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.
2020-05-09 20:00:26 +01:00
Mark Liversedge
3f92810240 Datafilter - median() and mode()
.. vectorized like mean() and sum() etc. Do what you expect and return
   the median and mode values.
2020-05-09 19:01:19 +01:00
Alejandro Martinez
fc00d28873 Update issue template
[skip ci]
Fixed reference to contributing guidelines
2020-05-09 13:39:02 -03:00
Mark Liversedge
7daf2fa63e DataFilter - dist()
.. 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.
2020-05-09 15:59:38 +01:00
Mark Liversedge
eec8d6616c Datafilter - nozero()
.. 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.
2020-05-09 12:38:26 +01:00
Mark Liversedge
9bd6cff3e3 Fix scatter plot hover <25 points
.. 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.
2020-05-08 21:33:15 +01:00
Mark Liversedge
d3c04e27fa Fix metric refresh SEGV
.. 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)
2020-05-08 20:05:31 +01:00
Mark Liversedge
fd0a5955ef Fix some metric refresh SEGV
.. 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.
2020-05-08 14:31:43 +01:00
Mark Liversedge
4029c3a9aa Datafilter - match()
.. 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
2020-05-08 12:58:30 +01:00
Ale Martinez
c1edbcb00a Add GSL to CI builds
Complements c973328779
[publish binaries]
2020-05-07 16:25:45 -03:00
Ale Martinez
fcc9660b64 Upload binaries to S3
Only for commits to master with [publish binaries] in the commit message
Older binaries are removed, we keep only the last succesful build.
2020-05-06 21:19:24 -03:00
Mark Liversedge
532b29b9d1 Datafilter vector - mlr()
.. 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.
2020-05-06 20:20:12 +01:00
Mark Liversedge
c973328779 Introduce GNU Scientific Library (GSL) as an optional dependency
.. 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
2020-05-06 18:32:16 +01:00
Ale Martinez
76d459a895 Cache qwt in Travis and AppVeyor to reduce build time
Warning: the cache needs to be invalidated for changes in qwt to take effect
2020-05-05 19:51:45 -03:00
Ale Martinez
b6eabc63d1 AppVeyor - Remove zip generation and rename installer
Since the installer is working we don't need the zip anymore
[skip travis]
2020-05-04 12:14:50 -03:00
Ale Martinez
e7aaebcd00 Revert "Add version string for non tag builds"
[skip ci]
This reverts commit 7d06cd5ad1.
2020-05-02 15:19:09 -03:00
Ale Martinez
7d06cd5ad1 Add version string for non tag builds
Used to build binaries for the release, will be reverted afterwards.
2020-05-02 15:15:50 -03:00
Ale Martinez
cc11f1fa2d AppVeyor - Add version string for Tag builds 2020-05-02 15:14:49 -03:00
Ale Martinez
4cd24bc09a Travis-CI - Upgrade to Python 3.7 2020-05-02 14:12:01 -03:00
Ale Martinez
a4dbfa69d3 AppVeyor - Upgrade to Python 3.7 and remove console 2020-05-02 14:11:35 -03:00
Mark Liversedge
d042ec591e Fix crash on --no-python
.. 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.
2020-05-02 14:07:57 +01:00
Mark Liversedge
211b9b23cd VERSION 3.6 DEVELOPMENT MAY 2020
.. first development release for v3.6
2020-05-01 18:37:01 +01:00
Mark Liversedge
d6c16dd9de User Chart Time Axis Bug
.. 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.
2020-05-01 13:53:22 +01:00
Alejandro Martinez
e1db9c832f Fix Travis-ci builds for macOS - Add QWebEngine dependence
[skip appveyor]
QWebEngine depends on QtQmlModels and QtQml in Qt5.14.2
2020-04-30 21:35:43 -03:00
human705
05ee4f40da Add Elevation Widget to Train Video Overlays (#3411)
* 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>
2020-04-30 19:26:40 -03:00
Mark Liversedge
a0add0bdc9 Security alert - Remove jquery and related
.. 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
2020-04-30 21:43:30 +01:00
Ale Martinez
a9ddef9667 Fix Travis-ci macOS builds
[skip appveyor]
icu4c was upgraded from 64 to 66 and the dmg patch failed.
Lets make the hack a little more generic
2020-04-30 15:08:35 -03:00
Mark Liversedge
d69fa7986f User Chart Series Errors Wrapping
.. when editing a user chart series program the errors in red at the
   bottom of the dialog get truncated instead of word wrapping.
2020-04-29 20:45:40 +01:00
Ale Martinez
3ff380ce0f Travis-ci Linux builds - Update to Qt 5.14.2 2020-04-29 16:11:57 -03:00
Ale Martinez
c0bed13cfa Add vlc plugins to Linux AppImage for Travis-ci builds
This avoids the need to install vlc 2.2 and set VLC_PLUGIN_PATH
Fixes #3394
2020-04-29 15:17:26 -03:00
Mark Liversedge
794efdaf06 DataFilter - exists()
.. exists("symbol") will tell you if the symbol exsits as either a
   function or a variable.
2020-04-29 18:49:04 +01:00
Ale Martinez
5e54c994b7 AppVeyor - Build Windows 64bit installer and add to Artifacts
Installer script cleanup to remove unused dependencies
2020-04-29 11:29:49 -03:00
Erik Botö
0a1b0846ce Add VO2 and Ventilation graphs to WorkoutWidget and add settings (#3415)
* 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.
2020-04-29 08:03:02 +01:00
Ale Martinez
28645ff7b0 AppVeyor - Add installer script
The installer building step is disabled, but it can be executed
offline using NSIS 3.05
2020-04-28 21:03:16 -03:00
Ale Martinez
ff433dcf76 AppVeyor - Use cache to reduce build time
Avoid downloading cached files from to reduce dependence on external services
We are too close to the 1h limit to depende on variable time downloads
2020-04-28 20:46:53 -03:00
Ale Martinez
429b5de44c AppVeyor - Add ReadMe, license, and icon files
We need them to generate an installer
2020-04-28 16:04:42 -03:00
peterbrant14
0fab9b901a Fix indexing bugs in the original TTS code (#3423) 2020-04-28 17:45:21 +01:00
Mark Liversedge
2e228ef52b Increase max Crr to 0.025
.. plausible value for knobbly tyres over sand or soft woodland.
2020-04-28 08:10:15 +01:00
Erik Botö
13b80dfda6 VMPro: Add possibility to start calibration manually (#3414) 2020-04-27 15:10:34 -03:00
Erik Botö
09dea59996 Enable BT on Windows (#3401)
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
2020-04-27 13:50:19 -03:00
Erik Botö
4ae3d47d10 AppVeyor - Don't use parallel build for QWT (#3420)
Seems like QWT sometimes fails when using parallel build, so use -j1
when building it to force non-parallel build.
2020-04-27 11:02:45 -03:00
Mark Liversedge
3aca25c681 User Chart Program Editor Size
.. just make it bigger, so easier to see the whole thing, and also
   fixed up scaling as resizing the window.
2020-04-27 14:29:24 +01:00
Erik Botö
0caa399e06 AppVeyor - Update to Qt 5.14.2 (#3419)
Update to Visual Studio 2019 image, which now has Qt 5.14.2.
2020-04-27 09:04:42 -03:00
Ale Martinez
8fe784c8d2 AppVeyor - Remove upload to transfer.sh
It is not required since artifacts are more convenient and reliable.
2020-04-26 19:00:37 -03:00
Mark Liversedge
ed33157945 Minor Datafilter fixups
.. 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.
2020-04-26 21:53:50 +01:00
Ale Martinez
75c3039358 AppVeyor - Enable CloudDB for Windows CI builds
Missing from previous commit
2020-04-26 11:54:03 -03:00
Ale Martinez
d5fffcc8fa Generate AppVeyor artifact before upload
This is a required step to upload to GitHub releases.
Don't fail on transfer.sh unavailability.
2020-04-25 21:27:56 -03:00
Ale Martinez
a853ce9e9d AppVeyor - Add secrets for Windows ci builds
To enable access to online services
2020-04-25 12:58:18 -03:00
Mark Liversedge
d399d1ce4c Fix month and friends to work with vectors
.. a cut and paste error !
2020-04-25 10:47:52 +01:00
Mark Liversedge
a82e1467b5 Datafilter vectors - aggregate()
.. 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.
2020-04-25 09:57:33 +01:00
Ale Martinez
c6dd6a1f64 AppVeyor - Add VLC plugin folder
Also enabled Robot and console for testing and debugging purposes.
2020-04-24 22:33:54 -03:00
Mark Liversedge
adc9fc84cd DataFilter vectors - date arithmetic
.. 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.
2020-04-24 20:59:27 +01:00
Ale Martinez
df268b7e6f Add vlc version to versionHTML
To help identify issues with VLC version mismatch at runtime
2020-04-24 15:47:31 -03:00
Ale Martinez
95d0e330b0 Add Python version used a build time to versionHTML
Similar to R, useful to determine which Python version is required.
2020-04-23 12:54:56 -03:00
Ale Martinez
0398bcdea3 AppVeyor - Add Python 3.6 to Windows ci builds
Using sip 4.19.8
2020-04-23 12:53:52 -03:00
Ale Martinez
0ed1ad86a7 AppVeyor - Add R integration to Windows ci builds 2020-04-22 15:23:03 -03:00
Ale Martinez
521b507b18 Import Location and Equipment metadata from fitlog files
Fixed #3406
2020-04-22 11:34:10 -03:00
Ale Martinez
ecc8c9b593 AppVeyor - Upgrade to VS 2017 and Qt 5.12
Use jom to reduce build time
Add OpenSSL 1.1.1 libraries
2020-04-21 21:17:40 -03:00
Ale Martinez
613ddbda81 Trends Summary - Add Sport column to xtrain activities 2020-04-21 21:17:40 -03:00
Mark Liversedge
2735d8969a Fix Generic chart hover
.. 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()
2020-04-21 20:58:35 +01:00
Mark Liversedge
7a0ed0792b Datafilter vectors - measures()
.. 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.
2020-04-21 10:49:46 +01:00
Ale Martinez
1167cdd582 Add Edge 530 id to FitRideFile
Fixes #3404
2020-04-20 17:18:28 -03:00
Ale Martinez
d8f68a93f0 Add D2XX to AppVeyor Windows ci builds
Moved all libraries to the same folder
2020-04-20 16:22:46 -03:00
Mark Liversedge
368da6d075 DataFilter vectors - cumsum()
.. cumsum(v) returns a cumulative sum of the contenst of vector v.
2020-04-20 12:10:23 +01:00
Ale Martinez
0f2dae05bb AppVeyor - Copy dependencies and Upload build result to transfer.sh
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.
2020-04-19 14:56:10 -03:00
Mark Liversedge
33d5c1fe2b Cosmetic Updates
.. 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.
2020-04-19 14:42:36 +01:00
Mark Liversedge
b97eca37ff PeakPowerIndex, UserChartData and Overview Fixups
.. 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)
2020-04-19 10:06:27 +01:00
Ale Martinez
29fcc6aafe Add detailed version information to --version command line option
Similar to About > Version, used to provide more information after ci builds
Also --usage is added as synonimous for --help for completeness
2020-04-18 15:32:22 -03:00
Mark Liversedge
562cde58f4 Remove call to MainWindow::searchFocusOut on MacOS Build
.. it was deprecated.
2020-04-15 07:29:09 +01:00
Ale Martinez
7e77dd552a Include first record in exported CSV files with All Data
Fixes #3396
2020-04-13 13:29:19 -03:00
Mark Liversedge
e5b756b060 Align View menu with NewSideBar
.. need to keep in sync.
2020-04-13 13:26:02 +01:00
Mark Liversedge
8c4758cc7a ChartBar drag fixup for Qt5.10 regression
.. 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.
2020-04-12 22:57:34 +01:00
Mark Liversedge
856de3e1e5 ChartBar drag fixup
.. 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.
2020-04-12 21:36:41 +01:00
Mark Liversedge
c31d5c703f More accidental debug
.. this is becoming a bad habit. sorry.
2020-04-12 20:38:42 +01:00
Mark Liversedge
4b3c36464e ChartBar scroll left/right fix and animate
.. 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.
2020-04-12 17:01:32 +01:00
Mark Liversedge
7eeb4f9179 Remove debug output
.. errant code from debugging during development.
2020-04-12 14:10:52 +01:00
Mark Liversedge
ccc6345606 Re-arrange Tabs by dragging on the ChartBar
.. allow the users to rearrange the tabs by dragging and dropping them.
.. does not autoscroll, but could be added later for finesse.

Fixes #3395
2020-04-12 13:01:41 +01:00
Mark Liversedge
b051f30a7a Remove GcScopeBar.h include in Overlay Widget
.. breaks builds as GcScopeBar is deprecated and the include isn't
   needed anyway.
2020-04-11 21:44:16 +01:00
Mark Liversedge
c7515e040b Reinstate head toolbar color
.. Theme colors for chrome were not being applied to the main toolbar
   after the last commit. A couple of temporary hacks got left into the
   commit.
2020-04-11 21:29:57 +01:00
Mark Liversedge
587c631b82 Deprecate ScopeBar code, cleaner ChartBar
.. the chart bar used some of the code from the old scopebar widget so
   decoupled that and made it a little more modern.

.. GcScopeBar now deprecated
2020-04-11 20:56:59 +01:00
Mark Liversedge
28b242815b New Sidebar and deprecate Scope Bar
.. 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.
2020-04-11 15:34:22 +01:00
Ale Martinez
feacfefbf4 Fix small error in DataFilter metrics(Symbol,...)
The 2nd parameter of RideItem::getForSymbol is a boolean for metric/imperial,
passing c selects imperial units when metrics(Symbol,...) is used in LTMPlot.
2020-04-06 21:54:31 -03:00
Ale Martinez
42fa49c50f Add sport field to RideItem/RideDB as primary field
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
2020-04-06 19:13:43 -03:00
Mark Liversedge
f0315ccca5 DataFilter vectors - metrics date range
.. 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.
2020-04-05 12:42:01 +01:00
Mark Liversedge
c082ec50e9 Datafilter vectors - Date vectors
.. 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.
2020-04-05 10:58:58 +01:00
Mark Liversedge
39660ecc37 NewMainWindow Prototype - MacOS Native
.. 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.
2020-04-04 12:05:01 +01:00
riccioclista
685c176eca QwtPlotGappedCurve: Include the last point in the plot (#2678)
Also solves the same issue is present when plotting Measures in Trends.
2020-04-01 13:06:23 -03:00
Ale Martinez
77cf334f8a Add Device Wizard - Select Device screen capture for the wiki
[skip ci]
2020-04-01 11:23:32 -03:00
Mark Liversedge
18922e1316 NewMainWindow resizing
.. frameless window so we need to do it all ourselves.
   Works ok, so time to move onto titlebar with Mac.
2020-03-31 19:54:30 +01:00
Ale Martinez
b3f35597d3 Import Notes from TCX files
Fixes #3385
2020-03-29 22:41:48 -03:00
Ale Martinez
22c2cdd5d7 TcxParser - initialize for each activity to support multisession files
Fixes #3362
2020-03-29 22:30:01 -03:00
Ale Martinez
ecd6b13a26 Initialized WorkoutWindow to the currently selected workout
Fixes #3384
2020-03-29 20:12:45 -03:00
Mark Liversedge
f3e3209f32 NewMainWindow prototype - basic toolbar
.. 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).
2020-03-29 21:40:42 +01:00
Mark Liversedge
c9bca752cc NewMainWindow prototype - close, minimize
.. very basic, no icons. Just to be able to close
   gracefully. Need to get same level of functionality
   on windows and macOS.
2020-03-29 13:46:24 +01:00
Mark Liversedge
102b5dff15 NewMainWindow Protoyping
.. 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.
2020-03-29 12:25:53 +01:00
Ale Martinez
eaf54b692e Cloud Service Download - linked defaults and auto data processors
Fixes #3381
2020-03-28 11:49:47 -03:00
Alejandro Martinez
3c1adf90ef Update README.md
[skip ci]
2020-03-27 13:38:45 -03:00
Alejandro Martinez
43150e7c17 CloudDB sharing of Custom Metrics (#3370)
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
2020-03-26 15:03:44 -03:00
Mark Liversedge
4d1ef200bf UserChart & GenericLegend config nits
.. 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.
2020-03-26 17:57:59 +00:00
Mark Liversedge
afa5d01a31 Datafilter vectors - lowerbound()
.. 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)
2020-03-26 10:00:52 +00:00
Mark Liversedge
52dc384447 Fix user chart program regression introduced in last commit
.. 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).
2020-03-25 21:44:40 +00:00
Mark Liversedge
bda728696f Datafilter vectors - curve()
.. 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.
2020-03-25 21:12:37 +00:00
Mark Liversedge
b24869e1a8 DataFilter vectors - vectorize + - / * ^ operations
.. 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
2020-03-25 15:22:48 +00:00
Mark Liversedge
d32152f6dc Datafilter vectors - vectorize the trig functions
.. cos() et al now support vectors, so you can do e.g.
   a<-c(0,90,180,270); b<-cos(a);

.. need to also do the binary operations * / + - ^ next.
2020-03-25 14:33:20 +00:00
Mark Liversedge
8ee52edeee Datafilter vectors - stddev() and variance()
.. both take a single parameter (a vector) and compute the standard
   deviation and variance accordingly. sigma and sigma^2.
2020-03-24 20:01:17 +00:00
Mark Liversedge
74c8fddb1a Datafilter vectors - arguniq() and uniq()
.. 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.
2020-03-24 13:45:20 +00:00
Mark Liversedge
9282bd783e Fix windows compile error
.. bool function must return a value; Bindings::addAnnotation()
2020-03-22 18:56:29 +00:00
Mark Liversedge
ce89389451 Datafilter - meanmax(efforts)
.. 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.
2020-03-22 09:40:41 +00:00
Mark Liversedge
d36b39d31e Generic Plot Cosmetic
.. 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.
2020-03-21 08:34:49 +00:00
Mark Liversedge
987e79024f Fix select linear regress paint for time x-axis
.. scaling and transformation of x-value was needed before painting the
   linear regression line when using a time axis.
2020-03-20 18:39:17 +00:00
Mark Liversedge
63ebd5fc7c V3.6 Development Build Numbers
.. 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.
2020-03-20 10:01:41 +00:00
Mark Liversedge
3fab386fb2 PythonChart Toggle Web/Qt
Fixes #3375
2020-03-20 08:42:13 +00:00
Mark Liversedge
fc02b8a38b GenericChart Data Labels
.. 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.
2020-03-20 08:06:56 +00:00
Mark Liversedge
71690f32a7 Generic Chart Python Label Annotation - Part 2b of 2
.. 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.
2020-03-20 07:16:52 +00:00
Mark Liversedge
d3ba4b0f1e Generic Chart R Label Annotation - Part 2a of 2
.. 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.
2020-03-19 21:48:28 +00:00
Mark Liversedge
2a08c4c2b2 Nits from last commit
.. windows builds bork as bool function doesn't return anything

.. left in a couple of debug messages.
2020-03-19 19:43:01 +00:00
Mark Liversedge
e2e9fe63cf Generic Chart Label Annotation - Part 1 of 2
.. 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.
2020-03-19 17:30:52 +00:00
Mark Liversedge
917bbab173 Datafilter - bool()
.. 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.
2020-03-19 11:31:20 +00:00
Mark Liversedge
a4727c8a46 DataFilter - better error feedback
.. 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).
2020-03-19 10:45:00 +00:00
Mark Liversedge
323a97fb40 DataFilter - lm()
.. 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.
2020-03-18 21:06:24 +00:00
Mark Liversedge
d7603b7fa6 GenericPlot fixup hover/hide with decorations
.. 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.
2020-03-17 19:28:21 +00:00
Mark Liversedge
95eca909c1 Lines can have symbols, scatters can have lines
.. 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.
2020-03-16 16:30:36 +00:00
Mark Liversedge
4912f3731d Fix [index] reduce/reduce warning for Datafilter.y
.. 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.
2020-03-16 15:04:15 +00:00
Mark Liversedge
95365b647c Datafilter vectors - smooth() ewma
.. 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.
2020-03-15 21:23:59 +00:00
Mark Liversedge
0f5f44053f Datafilter vectors - smooth()
.. 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.
2020-03-15 20:22:42 +00:00
Mark Liversedge
3f9774b2c2 Generic Chart Series - show on legend
.. 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.
2020-03-15 18:43:11 +00:00
Mark Liversedge
cc462f49a3 Datafilter - deprecate [[ ]] "vectors"
.. 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.
2020-03-15 16:56:39 +00:00
Mark Liversedge
207e20a369 User Chart Screen Shots for wiki
Wiki page for user chart needs some pics.
2020-03-15 16:10:15 +00:00
Mark Liversedge
1231f59b1a DataFilter Grammar for [index]
.. 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....
2020-03-15 14:16:44 +00:00
Mark Liversedge
7f81ac76a9 Datafilter vectors - lr()
.. 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.
2020-03-15 11:38:30 +00:00
Mark Liversedge
48fbdbd542 Generic Plot Linear Regress with Time Axis
.. 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.
2020-03-15 09:08:59 +00:00
Mark Liversedge
7e0fcf32f9 Wiki screen grabs
.. some images to use on the wiki page for working with user charts.
2020-03-14 16:52:30 +00:00
Mark Liversedge
3559395c83 Fix [ expr ] when expr is a vector
.. 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.
2020-03-14 16:12:52 +00:00
Mark Liversedge
0125e2aadf DataFilter vectors - sapply(list, expr)
.. 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.
2020-03-14 15:34:30 +00:00
Mark Liversedge
cc0108d48f Datafilter vectors - selection with [ lexpr ]
.. 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.
2020-03-14 13:45:57 +00:00
Mark Liversedge
2b58c20cc9 DataFilter vectors - [] indexing
.. 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.
2020-03-13 19:47:27 +00:00
Mark Liversedge
ef97cc84a0 Data Filter vectors - banister()
.. 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)
2020-03-13 15:43:25 +00:00
Mark Liversedge
b1c9f7071b DataFilter vectors - pmc()
.. 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)
2020-03-13 14:17:38 +00:00
Mark Liversedge
87d1af5b13 Generic Plot Time Axis support
.. 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.
2020-03-13 10:11:50 +00:00
Mark Liversedge
694be2d111 Generic Plot DateTime Axis support
.. when plotting on trends view the x-axis is a date based range.

.. still need to update for time based axis when looking at activities.
2020-03-12 19:26:51 +00:00
Mark Liversedge
c0869f5caf GenericPlot auto axis min/max
.. set the axis min max from the series data if not set explicitly
   by the user. Especially useful for date ranges.
2020-03-12 15:48:43 +00:00
Mark Liversedge
3461af38d5 User Chart Part 2 of 2
.. 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.
2020-03-12 14:43:11 +00:00
Mark Liversedge
1e9f8ee174 UserChart user program (formula) re-design
.. 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.
2020-03-12 09:49:15 +00:00
Mark Liversedge
1740fd488b Fix datafilter meanmax memory leak
.. use stack not heap for temporary ridefilecache object.
2020-03-12 06:22:33 +00:00
ericchristoffersen
5ec95681f2 Optimize splines and bikesim dvdt. (#3349)
* Optimize splines and bikesim dvdt.

* Trig identity

* Refactor to provide WattsForV.

* Optimize gps route smoothing, spline distance.
2020-03-11 22:15:20 +00:00
ericchristoffersen
0676ce1d89 Derived stats for sim bicycle config screen (#3332) 2020-03-11 22:14:55 +00:00
Erik Botö
ab2c1048d1 Fix issue with font being "white on white" in dark-mode on Mac (#3331) 2020-03-11 22:00:30 +00:00
Mark Liversedge
66d1d47b1d DataFilter vectors - meanmax()
.. 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.
2020-03-11 20:30:03 +00:00
Mark Liversedge
96285c874c DataFilter vectors - argsort(), sort(), head(), tail()
.. 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.
2020-03-11 16:31:18 +00:00
Mark Liversedge
85fb985d2f DataFilter vectors - metrics()
.. metrics(symbol|date) will return a vector of metrics for the current
   date range selected on trends view honoring all the filters etc.
2020-03-10 18:08:16 +00:00
Mark Liversedge
44eded59b7 DataFilter vectors - samples()
.. 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.
2020-03-10 16:56:42 +00:00
Mark Liversedge
4ab6bd9809 DataFilter vector - mid()
.. mid(v,pos,count) no equivalent in R but returns a subset of another
   vector v starting from pos for length count.
2020-03-10 14:52:00 +00:00
Mark Liversedge
c0893c052a DataFilter vectors - append() and remove()
.. 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.
2020-03-10 14:22:58 +00:00
Mark Liversedge
98e224b10b DataFilter vectors - seq, rep, length functions
.. 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.
2020-03-10 10:50:53 +00:00
Mark Liversedge
70bef43ccd DataFilter vectors - c() function
.. 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.
2020-03-10 09:34:20 +00:00
Mark Liversedge
495dff77ca Generic Chart Slope Paint
.. 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.
2020-03-09 21:03:56 +00:00
Mark Liversedge
35a37ff846 Add QT Charts to R 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.
2020-03-09 19:40:17 +00:00
Mark Liversedge
9e7f843d43 Generic Plot log axes
.. add log axes support.
2020-03-09 11:06:54 +00:00
Mark Liversedge
b17c337979 Generic Plot Slope Fixups
.. 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.
2020-03-09 09:54:33 +00:00
Mark Liversedge
40983afa7b User Chart Opacity Setting
.. was missed in original commit.
2020-03-09 09:05:48 +00:00
Mark Liversedge
b8a6fd40e3 Fix generic plot missing top label on axis
.. when working out the hover area. this is because the first label
   is sometimes aligned above the plot area. so we look a little higher.
2020-03-09 08:35:11 +00:00
Mark Liversedge
67801f4ce7 Export Chart Dont Use Native Dialog
.. 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.
2020-03-09 08:04:06 +00:00
Mark Liversedge
4fd07e7688 Fix User Chart Axis Hover bug
.. 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.
2020-03-08 21:49:17 +00:00
Mark Liversedge
20b00ea33b User Chart Nits
.. 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.
2020-03-08 20:45:57 +00:00
Ale Martinez
a7debe567b Change Python and R season meanmax to honor left sidebar filters
Fixes #3369
2020-03-08 16:10:54 -03:00
Mark Liversedge
0f1224bb35 User Chart (Part 1 of 2)
.. 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.
2020-03-08 16:29:42 +00:00
Ale Martinez
d913e75402 REST API - use default metadata.xml when the file does not exist
Fixes #3368
2020-03-07 20:49:40 -03:00
Ale Martinez
95c1d822a7 Use thread-safe setUrlRequestInterceptor in WebPageWindow
When Qt version >= 5.13
Fixes #3365
2020-03-03 19:35:01 -03:00
Mark Liversedge
10ae17868d Fix jarring update GenericChart with multiple plots
.. 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.
2020-03-03 19:38:51 +00:00
Ale Martinez
c0b057a48d Strava - Upload Manual Activities
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
2020-03-03 11:15:10 -03:00
Mark Liversedge
876ce83c96 Add QChart to Python Chart (4c of 5)
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.
2020-03-02 20:11:56 +00:00
Mark Liversedge
85cbbc3840 Add QChart to Python Chart (4b of 5)
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.
2020-03-02 18:59:07 +00:00
Mark Liversedge
ce955e01a5 Add QChart to Python Chart (4a of 5)
.. 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).
2020-03-02 10:39:58 +00:00
Mark Liversedge
e83c9e8bb3 GenericPlot legend placement and line styles
.. 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.
2020-03-01 17:37:07 +00:00
Mark Liversedge
6ce905509f Add QChart to Python Chart (3i of 5)
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.
2020-03-01 10:03:47 +00:00
Mark Liversedge
ec24536f65 Blank texts break axes login in GenericPlot
.. 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
2020-02-29 16:47:50 +00:00
Mark Liversedge
c81576e311 Fix axis paint of cursor values in GenericPlot
.. 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.
2020-02-29 14:01:23 +00:00
Mark Liversedge
73be187b15 QAbstractAxis get rect
.. 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.
2020-02-29 11:50:06 +00:00
Mark Liversedge
85bdb48ab7 GenericPlot selector hover highlight
.. to indicate the selection area can be grabbed and moved. Just
   a minor UX tweak to help signpost interactive elements.
2020-02-28 20:26:33 +00:00
Mark Liversedge
40195ab0ce Fixup GenericPlot legend hover for pie and bar charts
.. the legend is mostly static for pie and bar charts
   but should be shown nonetheless.
2020-02-28 18:56:21 +00:00
Mark Liversedge
0ecfa0e67e Add QChart to Python Chart (3h of 5)
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.
2020-02-28 14:31:50 +00:00
Mark Liversedge
21d1e071bf Ignore '.' folders in ChooseCyclistDialog
.. mostly because this is good practice but also to avoid showing
   the .pyfixes folder.
2020-02-28 09:14:34 +00:00
Mark Liversedge
f4d954c3ee Initialise Calc member variables
.. rather egregiously did not set any to zero etc and expected
   cummulative ops to just work. they didn't.
2020-02-28 09:13:31 +00:00
ericchristoffersen
426c28b961 Remove CRS_LOC. (#3352) 2020-02-27 15:58:37 +00:00
ericchristoffersen
da3e8212cf Allow TTS Files for VideoSync. (#3354)
Rewrite TTSReader Stream Merge

Add gpi reset.
2020-02-27 15:56:42 +00:00
Mark Liversedge
cee6f0329a GenericPlot refactor source files
.. 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).
2020-02-24 20:20:57 +00:00
Mark Liversedge
37ebd06564 Generic Plot tidy up state transitions
.. fix a few nits when moving between states for the selection tool
   and updating the display.
2020-02-24 19:00:00 +00:00
Mark Liversedge
5ad1f1624d Fix GenericPlot performance when select active
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.
2020-02-24 17:48:57 +00:00
Mark Liversedge
bbc0a1f0ea Add QChart to Python Chart (3g of 5)
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.
2020-02-24 17:16:25 +00:00
Mark Liversedge
0da3142f6b Fix line chart legend when series missing
.. 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.
2020-02-24 11:49:46 +00:00
Mark Liversedge
16a5cb0c6f X-Axis in Generic Plot Legend
.. to show the current x-axis value, missed off when concentrating
   on showing y-axis values for the data series.
2020-02-24 11:08:09 +00:00
Mark Liversedge
ad3024ac7f Add QChart to Python Chart (3f of 5)
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.
2020-02-24 09:22:48 +00:00
Ale Martinez
0035530f29 Add some validations to User Metrics creation and modification
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
2020-02-22 21:15:06 -03:00
Mark Liversedge
03acacbd7d Some minor Generic Plot fixups
.. 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.
2020-02-22 06:16:48 +00:00
Ale Martinez
635eccd001 Add custom metrics export and import to .gmetric files
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
2020-02-21 19:07:47 -03:00
Ale Martinez
6659262ae2 Fix Travis-ci build matrix configuration
There were errors and warnings in config due to format issues
and deprecated keywords.
2020-02-21 17:54:11 -03:00
Mark Liversedge
78e74ddaa9 Add QChart to Python Chart (3e of 5)
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.
2020-02-21 20:00:43 +00:00
Ale Martinez
78b94c9d8f Upgrade travis-ci builds to Qt 5.14.1 2020-02-20 11:29:45 -03:00
flo
fae2b935e1 Support Multisport fit files
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
2020-02-19 17:45:53 -03:00
flo
5ecc2470aa Allow deep copies of XDataSeries
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.
2020-02-19 17:45:53 -03:00
Mark Liversedge
0495cb786d Add QChart to Python Chart (3d of 5)
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).
2020-02-19 09:02:58 +00:00
Ramon van Belzen
706b79f8fc travis-ci: force cpp detection 2020-02-18 12:25:51 -03:00
Ale Martinez
022d403f97 Quadtree Compile nits
Even when it is passing ci they give problems on my local build
2020-02-18 12:22:00 -03:00
Mark Liversedge
fe05d635e6 Generic Plot Selection Tool and OpenGL
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).
2020-02-18 09:53:10 +00:00
Mark Liversedge
902c18078e Fix misleading comment 2020-02-18 09:12:00 +00:00
Mark Liversedge
6fb3baae95 Add QChart to Python Chart (3c of 5)
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?)
2020-02-18 07:59:15 +00:00
Ale Martinez
6d3811f981 Add default name and extension to Export Chart Image
Name defaults to chart Title, similar to Export Chart
Extension defaults to .png bug .svg is also supported for high definition
printing.
2020-02-17 16:24:06 -03:00
Ale Martinez
279919a747 Add default .erg extension to Workout Editor Save As
When a valid extension is not included by the user
Fixes #3342
2020-02-17 16:15:04 -03:00
Ale Martinez
2efe686c14 Changed QStringList to QSet<String> in FilterSet implementation
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.
2020-02-17 12:55:47 -03:00
Mark Liversedge
4c9f237c20 Fix Generic Plot Flickering
.. the chart was being redrawn as series added because initialiseChart()
   was removing axes, be waiting until finaliseChart() to do this we
   avoid the flicker.
2020-02-17 11:21:39 +00:00
ericchristoffersen
d755a3a892 Trainmode must honor slope unless ergfile opts out. (#3346) 2020-02-17 08:22:17 +00:00
Mark Liversedge
226d704f1d Quieten down selection tool painting
.. 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.
2020-02-17 08:19:46 +00:00
Mark Liversedge
b60bb0e6db Settings.h missing compile error
.. needed for GenericPlot.
2020-02-16 22:45:45 +00:00
Mark Liversedge
0c3d748424 Add QChart to Python Chart (3b of 5)
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.
2020-02-16 21:19:50 +00:00
Mark Liversedge
ab4601cc33 Add QChart to Python Chart (3a of 5)
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.
2020-02-16 13:49:23 +00:00
Mark Liversedge
70e31235ed Refactor QChart out of PythonChart into GenericPlot
.. 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.
2020-02-15 09:32:34 +00:00
ericchristoffersen
127166a0e9 Support for TTS files. (#3333)
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.
2020-02-13 21:58:31 +00:00
Ale Martinez
48670ff566 Setup Duration, initial sample bracketing and metrics for erg2 files
Parsing is correct, but without this initialization they cannot be executed.
Fixes #3338
2020-02-11 20:56:34 -03:00
Mark Liversedge
1b3792d4a8 Add QChart to Python Chart (2b of 5)
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.
2020-02-11 17:41:46 +00:00
Ale Martinez
3cae9815c4 Enable workout import via Drag and Drop only in Train View
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
2020-02-11 13:23:35 -03:00
Mark Liversedge
54dc089705 Add QChart to Python Chart (2a of 5)
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.
2020-02-10 19:19:28 +00:00
Joern
8f33ebdd3d Merge pull request #3339 from Joern-R/CDB-Picture-Size
CloudDB - Chart Upload
2020-02-10 17:33:14 +01:00
Joern
125ecbb4bb CloudDB - Chart Upload
... Limit picture size to not go beyond max. size for CloudDB datastore call
2020-02-10 16:39:55 +01:00
Mark Liversedge
d88a94fa7d Fix SEGV Python/QT change chart type
.. needs to be done via the right thread and the qmap
   should be cleared to avoid double free crash.
2020-02-10 12:44:16 +00:00
Mark Liversedge
b4eb1191fd Add QChart to Python Chart (1 of 5)
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.
2020-02-10 11:57:42 +00:00
Erik Botö
d1e2f38e07 Add support for VO2 measurements and VO2Master VM Pro
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.
2020-02-03 12:00:08 +00:00
ericchristoffersen
67384872d0 Implement kinetic energy simulation
Implement kinetic energy simulation
BikeSim values into athlete data with ui.
Add ui for sim constants, also tooltips

Fixes #3261
2020-02-02 08:27:30 +00:00
ericchristoffersen
9018ad7a28 Use tangent vector to compute interpolated grade.
Use tangent vector to compute interpolated grade.
Implement correct bracket mapping for cubic spline
Case sensitive include file name.

#Fixes #3283
2020-02-02 08:26:21 +00:00
Mark Liversedge
46514538b5 Train view layout
.. was out of date.
2020-02-01 21:48:52 +00:00
ericchristoffersen
cf5d0d1f29 Issue 3320: FixGPS: Route Smoothing and Multipass Outlier Removal (#3321)
* FixGPS: add outlier removal

* Parameterized multipass route smoothing.

* Better defaults. Fix avgSlope calcs.

* Cleanup.
2020-02-01 17:16:24 +00:00
Mark Liversedge
8ea4524630 DPI Scale errors
.. overview window constraints on size

.. workout editor hide toolbar when small
2020-02-01 17:10:51 +00:00
Ale Martinez
2ef1f407b5 Workout Chart - Reset cadence during multiple training sessions
Copy/Paste error
Fixes #2251
2020-02-01 09:46:03 -03:00
mayerflash
a0ed8d020f Add support for Ergofit Bike (#3324) 2020-01-31 14:24:05 +00:00
Mark Liversedge
071cb35d15 Add Device Wizard Scroll Devices
.. add a scroll area when listing device types to add since there
   are so many of them these days (!)
2020-01-31 14:08:59 +00:00
Erik Botö
2c0eb835d4 Fix import of HRV from Fit files where single records occur (#3323)
* 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
2020-01-28 20:19:53 -03:00
ericchristoffersen
6e5fb42171 Add BSpline altitude smoothing to FixGPS. (#3310)
Fixes #3302
2020-01-27 10:57:39 -03:00
Poncho
40d03c4402 Add New Device IDs for FIT files (#3315)
add Garmin Edge 830
add Stages Cycling
Add test file for Garmin Edge 830 with Stages Cycling power meter
2020-01-26 18:52:13 -03:00
Alejandro Martinez
e64b6fb557 Allow Estimate Distance to run automatically without crash (#3313)
Fixes #3311
2020-01-25 19:48:58 -03:00
thebaron06
8a94666e91 Add the identification of Garmin HRM-Tri and Vector 3
Fixes #3306
2020-01-25 09:12:45 -03:00
Kamen Naydenov
1bf8f43f0a Add Garmin Instinct device ID (#3300)
Device information:
https://buy.garmin.com/en-US/US/p/621802/pn/010-02064-00#specs
2020-01-23 09:06:19 -03:00
Mark Liversedge
835f7cff92 Add Sync from Cloud for new athlete
.. 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.
2020-01-20 18:50:42 +00:00
Ale Martinez
8c775e5d2f Disable Qt5 video for macOS travis-ci builds
It buils but makes Train mode to chash
2020-01-20 10:23:10 -03:00
Mark Liversedge
16fc7a192b GPL2 in about box
.. was pointing to GPL3 which we downgraded from last year.
2020-01-18 20:22:08 +00:00
Ale Martinez
432926f4b9 Revert "Travis-ci build Linux AppImage with version string for v3.5 re-issue"
[skip ci]
This reverts commit 5c47bdb633.
2020-01-17 19:21:06 -03:00
Ale Martinez
5c47bdb633 Travis-ci build Linux AppImage with version string for v3.5 re-issue
To avoid creation of a new tag
2020-01-17 18:00:44 -03:00
Mark Liversedge
e90ba2e567 3.5 BUILD INCREMENT
.. re-issue of 3.5 binaries with Strava API guideline compliance, as
   part of the 'rate limit' requirements.
2020-01-17 20:15:28 +00:00
Mark Liversedge
fca5d9eb20 Connect with Strava
.. 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.
2020-01-17 16:04:27 +00:00
Mark Liversedge
2914f16e89 Compatible with Strava
.. logo added to the about box, only tested on hi-dpi display
   (may need scaling applied for lower resolution displays).
2020-01-17 14:49:16 +00:00
Mark Liversedge
878b281ffc View on Strava
.. 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/
2020-01-17 12:30:29 +00:00
rb83421
a92833f919 Python Embedding - Add flush function to class CatchOutErr
It does nothing for now
Fixes #3293
2020-01-16 15:59:53 -03:00
Alejandro Martinez
ba2213bb73 Remove ampersand from menu and button text before compare (#3298)
To avoid issues with kde injecting them, it is not pretty
but simple and safe.
Fixes #1852
Fixes #2930
2020-01-16 15:53:07 -03:00
Alejandro Martinez
2c20561caa Update ISSUE_TEMPLATE.md 2020-01-15 20:58:30 -03:00
Ale Martinez
17541b373d Revert "travis-ci - build linux AppImage with version string for v3.5 release"
This reverts commit c6691bf2d7.
[skip ci]
2020-01-13 21:24:08 -03:00
Ale Martinez
c6691bf2d7 travis-ci - build linux AppImage with version string for v3.5 release
This is a temporary hack to avoid creating a new tag
2020-01-13 17:51:39 -03:00
Mark Liversedge
151c98d8cc SEGV on Overview Chart
.. when no rides available on new user.

Fixes #3295
2020-01-13 20:21:31 +00:00
Mark Liversedge
21bf52c786 Version 3.5 release presentation
Slides used during the 'What's new in v3.5' video
2020-01-13 15:34:09 +00:00
Ale Martinez
c42f06f727 Add screen captures for the wiki - Web Chart 2020-01-13 12:20:10 -03:00
Ale Martinez
46107635c2 Add screen captures for the wiki - Cloud Accounts and sync
[skip ci]
2020-01-11 18:31:31 -03:00
Mark Liversedge
435e8e9bd5 VERSION 3.5 RELEASE
.. version and build number.
2020-01-10 16:51:47 +00:00
Mark Liversedge
9df093cff6 Overview to defaul layout 2020-01-10 16:38:42 +00:00
Ale Martinez
a35e09fd0a Withings download - disable debug
In preparation for v3.5 release
2020-01-09 20:31:43 -03:00
Ale Martinez
cd9f130b4b Add Body Measures Download screen capture for the wiki
[skip ci]
2020-01-09 20:30:58 -03:00
Alejandro Martinez
a5b9409789 Merge pull request #2837 from peterbrant14/Fix_RLV_Sync
Improve RLV Syncronization
2020-01-08 16:10:02 -03:00
peterbrant14
7cce47526f Allow for RLV files with no final speed indicator
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.
2020-01-07 17:48:57 +00:00
peterbrant14
49bc592a56 Improve RLV video syncronization.
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.
2020-01-07 17:48:57 +00:00
peterbrant14
3f177cae9e Fix truncation of Workouts with respect to pgmf file and corresponding rlv
Add a final point to the ErgFilePoint list to terminate the last section of the ride
2020-01-07 17:48:56 +00:00
peterbrant14
721cd2646b Fix error in RLV distance calculation when using ffwd or rwd
In guiUpdate, don't add manualOffset from VideoSyncFile.cpp when updating displayWorkoutDistance
as its already been included in the km value.
2020-01-07 17:48:56 +00:00
Ale Martinez
24fad147d0 Workout Wizard - Save distance in km since header indicates METRIC
Conversion is required when imperial units are used
Also fixed cumulative distance in Gradient case
Fixes #3288
2020-01-07 13:46:12 -03:00
Joern
db2de2be1f Merge pull request #3287 from Joern-R/tp
Today'sPlan Integration
2020-01-06 14:44:29 +01:00
Ale Martinez
744f6c79d4 Fix LTMPlot behaviour when there is only one group in date range
Fixes #3281
2020-01-06 10:14:12 -03:00
Joern
3728615c09 Today'sPlan Integration
... also synchronize Swim and Run activities
2020-01-06 13:45:44 +01:00
Ale Martinez
9e16d1dbf0 Map newlines to html <br> tags on CloudDB chart descriptions
When displayed on tableWidget, newlines are already preserved
across cloudDB interactions.
Fixes #3286
2020-01-05 13:41:33 -03:00
Ale Martinez
f385831d5e Enable Qt5 video for macOS travis-ci builds
Experimental build until #2242 is implemented
2020-01-05 12:22:55 -03:00
Ale Martinez
0887acdc89 travis-ci don't remove qt5 since it is required by other software
This error prevented to upload the generated dmg
2020-01-02 19:34:55 -03:00
Ale Martinez
8d6ea4fa72 Strava Download - Map VirtualRun and VirtualRide to Run and Ride
Use SubSport to preserve the original type when Sport is mapped.
Fixes #3278
2020-01-01 15:07:40 -03:00
Ale Martinez
4b53b24669 Fix previous commit
load instead of target
2019-12-31 13:14:52 -03:00
Alejandro Martinez
9524d56966 Video Overlays - Move HRM units from code to config file
To give more flexibility to users willing to use circular meters for HRM
2019-12-31 09:36:26 -03:00
Ale Martinez
29d28c93f4 Veloclinic Chart - Refresh when CP changes in Trends View
Fixes #3277
2019-12-30 15:01:25 -03:00
Jan Dvořák
edb2340b35 Czech translation (#3276)
Translate to Czech - Part 2
2019-12-30 08:18:01 -03:00
Ale Martinez
5ee004f355 Added Python Fixes Screen Captures for the wiki
[skip ci]
2019-12-29 10:14:55 -03:00
Ale Martinez
6eea504796 Fix travis-ci macOS builds 2019-12-28 14:31:19 -03:00
ericchristoffersen
4eae552846 Fix Issue 3273: Busy Hang in FixDeriveDistance (#3275)
Fix #3273: Busy Hang in FixDeriveDistance
Init goodii to 0 so tolerate no valid points.
2019-12-28 05:17:07 -03:00
Ale Martinez
26723b2755 Add missing QMap include to PowerProfile.h
Some toolchains report an error
Fixes #3270
2019-12-23 23:46:53 -03:00
Ale Martinez
b0d3e08ef9 Update default charts to remove remaining TSS and IF references
Replaced by BikeStress and BikeIntensity
2019-12-23 10:25:18 -03:00
Ale Martinez
f0482bf00c Revert "Plot R-R from Xdata"
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.
2019-12-20 18:00:30 -03:00
riccioclista
9f1187390f Python data processors (#2951)
* 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
2019-12-19 22:05:51 -03:00
Ale Martinez
a3e6ab8e09 Video Overlays - Load is target power or Slope according to mode
Similar to DialWindow
Added to sample video-layout.xml and adjust positions
2019-12-15 17:20:06 -03:00
Ale Martinez
e06c93ca0e CPPlot - Show as percentage only applies to ride curve
Fixes #3260
2019-12-15 10:26:04 -03:00
Alejandro Martinez
edb53806d8 Video Overlays - Add Distance as source
honoring metric/imperial setting.
Fixes error on Speed when imperial units are used.
Adds Distance to video-layout.xml and adjusts widget positions.
2019-12-15 00:08:49 -03:00
Ale Martinez
145d5ccae6 Fix travis-ci Linux builds
Fix libpulse-dev install and change python3.6 source
2019-12-14 23:05:57 -03:00
Ale Martinez
a2a94b3b41 Video Overlays - Speed widget honors metric/imperial setting 2019-12-14 21:13:45 -03:00
Ale Martinez
5fa59d1cf8 get Strava description
Save to Notes if Notes is not already used for name.
Complements d1e0e13ce1
2019-12-14 21:11:25 -03:00
Ale Martinez
c0889179da Remove deprecated CFBundleGetInfoString from info.plist
Fixes #2938
2019-12-11 14:34:52 -03:00
Ale Martinez
bc6ca7fee1 Added CFBundleVersion and CFBundleShortVersionString to Info.plist
Also updated values for the comming v3.5 release.
Fixes #2938
2019-12-11 12:49:04 -03:00
Quentin Heath
96b36aef0d fix am/pm time for HRV 2019-12-09 17:56:19 -03:00
ericchristoffersen
03e8da2c92 Issue 3241: Fix variance control in FixPowerSpikes (#3253)
Fixes #3241
2019-12-09 17:12:03 -03:00
Stranger
5420d92cc1 Update Russian translation (#3252) 2019-12-09 16:47:01 -03:00
Quentin Heath
d1e0e13ce1 add Strava description
direct copy from `Notes` (with UTF8 charset, as for the Strava title),
except if `Notes` was already used for the title
2019-12-09 16:15:46 -03:00
Quentin Heath
c978d6eb80 fix Strava title encoding
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
2019-12-09 16:15:46 -03:00
Jan Dvořák
5df46eebc7 Translate to Czech, part 1, 2725/5426 2019-12-08 21:17:57 -03:00
Ale Martinez
2cb9bc113e Export Chart Image as SVG
Add .svg as an alternative format for high resolution printing.
Fixes #3246
2019-12-08 20:07:06 -03:00
Ale Martinez
0009c280a8 Fix Export Chart Image in Tiled mode
Use rect instead of geometry to grab the complete widget.
Tested on Windows and Linux
Fixes #3055
2019-12-08 20:07:06 -03:00
Ale Martinez
715dc15133 Enable travis-ci tagged builds
To have binaries with version string set automatically and remove
the temporary hacks.
[skip ci]
2019-12-08 11:59:52 -03:00
Ale Martinez
657bb70d23 Define version string for travis-ci builds
To restore lupdate for OSX and to force new build with version strings
since tag builds are rejected. This will be fixed in next commit.
2019-12-08 10:16:50 -03:00
Mark Liversedge
feac0e86db VERSION 3.5 RELEASE CANDIDATE 2X
.. fix save ridecache
.. regenerate on first run to fix
2019-12-08 08:40:34 +00:00
Alejandro Martinez
c39b01279a Fix Travis-ci Linux builds
The ppa for vlc 2.2.8 is no longer available, fallback to vlc 2.2.2
2019-12-07 23:38:17 -03:00
Ale Martinez
9fec594d41 RideCach::save uses item instead of intervals to access interval metrics
This error was introduced in fa9a59d60c
Fixes #3244
2019-12-07 19:44:25 -03:00
Ale Martinez
14ee925645 travis-ci - define GC version string only for tagged builds
Commplements previous commit used to get binaries with version strings
once the tag was already set.
2019-12-06 12:10:54 -03:00
Ale Martinez
c2f3f2b8e2 Define GC version string for travis-ci builds
Next commit will do this only for tagged builds
2019-12-06 10:31:58 -03:00
Mark Liversedge
b818486aac VERSION 3.5 RELEASE CANDIDATE 2 2019-12-05 20:19:55 +00:00
Stranger
afdc860676 Add Garmin GPSMap 66 device (#3240)
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).
2019-12-05 10:21:24 -03:00
Stranger
1e2ef61b89 Update Russian translation (#3238) 2019-12-05 08:21:55 -03:00
Stranger
0aa24acd3d Fix non translatable strings in code (#3239) 2019-12-05 08:21:26 -03:00
Ale Martinez
43ab7d4afc Recognize Eric Christoffersen
Very useful contributions for v3.5 release
https://github.com/GoldenCheetah/GoldenCheetah/commits?author=ericchristoffersen
2019-12-04 17:49:16 -03:00
Ale Martinez
5bd4404279 Avoid endless loop on FIT files unknown type and negative size
Includes a test file to reproduce the issue.
Fixes #3229
2019-12-03 14:45:47 -03:00
Ale Martinez
4ed6927626 Merge branch 'ericchristoffersen-StartupSpeedup'
Closes #3235
2019-12-02 19:58:11 -03:00
Eric Christoffersen
fa9a59d60c Speedup critical string handling in RideCache Save 2019-12-02 19:54:48 -03:00
Eric Christoffersen
c13b24251e Speedup RideCache Load Time
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
2019-12-02 19:54:30 -03:00
Alejandro Martinez
b3a4b4a84e Update INSTALL-LINUX
Based on recent forum questions updated Qt version for v3.5, lupdate path and libz requirements.
2019-11-29 14:26:17 -03:00
Alejandro Martinez
cc633a7802 Add support for Device symbol on filters but disable set/unset/isset (#3233)
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.
2019-11-29 14:14:29 -03:00
ericchristoffersen
2b291f28b7 Issue 3230: Train mode compute altitude from slope (#3231)
Implements #3230
2019-11-27 21:49:13 -03:00
ericchristoffersen
2017d9162f 3227: Further optimize trends tracker table display (#3228)
Further speedups for trends tracking
Fixes #3227
2019-11-26 18:37:16 -03:00
Ale Martinez
6210d0a28d Fix QtWebEngineProcess deploy for travis-ci MacOS builds
This is a workaround for a bug in the homebrew version of macdeployqt
not present in Qt official binary distributions
2019-11-25 11:40:15 -03:00
Ale Martinez
fa7684a88d Fix Python deploy in MacOS travis-ci builds
Copy python framework and change path in binary
2019-11-24 17:31:33 -03:00
Ale Martinez
675cbcbe58 Add Tacx Neo Bike Trainer to ANT IDs
Contributed by Pavel Vasilyev
Fixes #3221
2019-11-24 09:21:38 -03:00
Ale Martinez
54b756b0ec Fix travis-ci MacOS builds 2019-11-24 09:21:38 -03:00
Joern
01490a64d1 Merge pull request #3226 from Joern-R/tp
Today's Plan Download
2019-11-23 20:16:16 +01:00
Joern
5db9440adb Today's Plan Download
... distance to be shown in sync. list is "double"
2019-11-23 19:28:32 +01:00
ericchristoffersen
6ca8e49a52 Fix 3222: Row append more efficient. (#3224) 2019-11-23 09:30:13 -03:00
Ale Martinez
7606697512 Added Note about qmake reporting missing translation files on first build
Similar to the one existing on INSTALL-WIN32
Fixes #3220
2019-11-22 11:54:11 -03:00
Ale Martinez
5da74f1136 Tag Multisport activities from FIT files correctly
Also remove unused Workout Code Tag
Partially fix #3211
2019-11-22 11:47:49 -03:00
Ale Martinez
45e73f7d34 Added Navicoach O-Synce sample FIT files
These uses non-interleaved mode for session records, we need to do
regression tests on these files for solutions to #3211
2019-11-21 13:05:05 -03:00
Ale Martinez
5383430b19 FitRideFile - Handle resync when HRM is unbucled
Fixes #3059
2019-11-21 09:41:34 -03:00
Ale Martinez
5cb0ed5b35 Added sample fit file for #3059 2019-11-21 09:37:13 -03:00
Henrik
43cabb2567 Swedish translation update (#3218) 2019-11-20 20:32:28 -03:00
Joern
5a4411f359 Merge pull request #3217 from Joern-R/DE
Update Translation DE
2019-11-20 15:30:25 +01:00
Joern
b4e82bb323 Update Translation DE 2019-11-20 14:43:24 +01:00
Ale Martinez
9536ed343b Enable Python for MacOS travis-ci builds
Using the Python version installed by Hombrew, currently 3.7.5
2019-11-18 20:55:32 -03:00
Ale Martinez
575a2b1c0b Fix path error on upload in previous commit 2019-11-18 13:04:24 -03:00
Ale Martinez
893f2a9b28 Upload travis-ci MacOS build results to transfer.sh
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
2019-11-17 23:09:29 -03:00
Ale Martinez
94eef9b6e0 Added secrets.h to Strava.cpp
Missing in bef37ea49c
The reason AppVeyor builds are failing
2019-11-16 09:06:34 -03:00
Ale Martinez
f5bcea85f0 Spanish Translation Update 2019-11-15 21:18:55 -03:00
Ale Martinez
bef37ea49c Strava OAuth Update - Handle Refresh Token
Complements ab18468a98
Fixes #3199
2019-11-15 18:27:09 -03:00
Ale Martinez
32ae63a2b5 Added Video Overlays Initialization on Windows builds with VLC
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
2019-11-15 10:27:30 -03:00
Alejandro Martinez
921765f9ef Add new sources for video-layout.xml meters (#3215)
Load, Time, LapTime, LapTimeRemaining and ErgTimeRemaining
Fixes #3213
2019-11-15 09:23:24 -03:00
grauser
8e46c5d2b6 lupdated 2019-11-14 13:56:13 +01:00
grauser
91d0ac1639 FitFile : QuickFix FloatValue can be Multi-Value
I probably have to refactor this code...

fix #3059
2019-11-14 13:54:05 +01:00
Alejandro Martinez
03516fb0cd Fix double fd close on RawRideFile (#3214)
Most of the time it is harmless, until it is not.
Fixes #2325
2019-11-13 20:40:51 -03:00
Michal
bf9b42d517 Add Garmin Edge 830 screenshot for extending the HRV Wiki page (#3206) 2019-11-12 08:38:02 -03:00
Alejandro Martinez
64ad946a1c Fixed BTLE Pair page in AddDeviceWizard to avoid ANT+ dependence (#3209)
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 #2771
Fixes #2983
2019-11-12 08:37:34 -03:00
Ale Martinez
df4e1f2fd7 Fix typo in Dutch translation
Fixes #3208
2019-11-09 11:38:49 -03:00
Ale Martinez
cc1ebdd827 Avoid duplicate time records in Train Mode
Fixes #3205
2019-11-05 21:26:45 -03:00
Ale Martinez
ab18468a98 Strava OAuth Update
According to https://developers.strava.com/docs/oauth-updates
Fixes #3199
2019-11-04 11:47:24 -03:00
Ale Martinez
5c4f72da6c Added virtual power support for Tacx Magnetic T1820
Fixes #1521
2019-10-29 22:55:59 -03:00
Ale Martinez
5cf76dd95c Added virtual power support for Elite Crono Mag Elastogel
Fixes #1538
2019-10-29 21:32:29 -03:00
Ale Martinez
a6875c583a Added virtual power support for CycleOps JetFluid Pro
Fixes #1809
2019-10-29 20:28:31 -03:00
Ale Martinez
a68cc8d179 Added virtual power support for Elite Turbo Muin 2015
Fixes #1575
2019-10-29 20:28:00 -03:00
Ale Martinez
26b5218ff3 Added virtual power support for Elite Crono Fluid Elastogel
Fixes #2720
2019-10-29 14:15:46 -03:00
Ale Martinez
a3dc4bca2d set AutoDefault to false on Curve Settings Push Buttons
To enable filter syntax checking on Enter
Partially reverts 43ed80d547
Fixes #3202
2019-10-29 11:50:55 -03:00
Ale Martinez
b236c76976 Filter bogus estimates when there is not enough data to fit the model
Just added a reasonable upper limit for CP
Fixes #3180
2019-10-28 16:32:50 -03:00
jgpallero
5a93a2c62f Update LeftRightBalance.cpp (#3189)
Add parenthesis in order to evaluate correctly the L/R balance computation
2019-10-28 14:01:09 -03:00
Ale Martinez
43ed80d547 Set Default buttons on LTM and Interval dialogs
Color is not a good option
Fixes #3202
2019-10-27 23:01:09 -03:00
Ale Martinez
5bdad6199e Fix FSF address
Fixes #2689
2019-10-26 21:55:53 -03:00
Ale Martinez
77547bfe55 Fix German translation to avoid metric name duplicates
Fixes #3187
2019-10-24 09:51:33 -03:00
Ale Martinez
beac898601 Fix units of work in tooltips for AllPlot and CPPlot
Also change wrong label in PMC (Coggan)
Fixes #3194
2019-10-21 21:56:05 -03:00
Ale Martinez
f9694775d3 MergeActivityWizard - preserve XDATA series order on join
and add the remaining ones to the end
Fixes #3183
2019-10-16 10:21:24 -03:00
Mark Liversedge
d01fdf55a7 VERSION 3.5 RC1
.. marking up for release candidate.
2019-10-14 09:53:51 +01:00
Ale Martinez
a065d480cd Make isSwim true when there are lap swim specific XData series
Similar to isRun when there are run specific standard series only when
Sport is not explicitly set.
2019-10-11 11:40:42 -03:00
Alejandro Martinez
0b0f99889e Enable import of XDATA series from CSV files (#3179)
* 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.
2019-10-10 23:16:22 -03:00
Ale Martinez
8b8ddccb5b Session RPE should not depend on HR Zones
Copy&Paste error, fixes #3171
2019-10-05 10:30:08 -03:00
Henrik
322a2c5265 Updated Swedish Translation (#3174) 2019-10-02 18:08:15 -03:00
Ale Martinez
eff123e0e2 Enable libusb 1.0 for travis-ci builds 2019-09-29 20:11:01 -03:00
riccioclista
c284885f8b Add libusb 1.0 support (#2919)
To fix freezes in Ubuntu and to support USB-C to USB-A dongles on MacOS
2019-09-29 20:09:09 -03:00
Ale Martinez
bb6d2552c0 Enable More menu in Overview to allow remove
Also blocke upload to cloud
These are temporary hacks until we have a proper config for Overview
2019-09-25 16:53:12 -03:00
Ale Martinez
1f4d6d1648 Fix OSX travis-ci build
libusb-compat depends on a newer libusb version that the one previously
installed giving an error.
Removing explicit libusb install fixes the issue.
2019-09-23 17:46:11 -03:00
Ale Martinez
be43cde4e1 Set min-height for Scrollbar handle in RideNavigator
When there are lots of activities the handle becomes too small to be useful,
so min-height is set to the same value as width to avoid this.
Fixes #2756
2019-09-23 14:35:43 -03:00
Ale Martinez
29db9ebde2 Add Direct navigation to year/month on Diary Calendar
Fixes #2756
2019-09-21 18:02:16 -03:00
Ale Martinez
6f50bc74e3 Garmin Fenix 5/6 new firmware uses enhanced speed and altitud fields
This maps them to correspoding standard fields
Fixes #3161 and #3168
2019-09-20 17:16:55 -03:00
Ale Martinez
b47ddd13d5 Change np to isopower in LTMTool formula helper 2019-09-20 17:16:55 -03:00
sanfordhk
411e85843c lupdated and fixed zh-tw translation of 'match' (#3167) 2019-09-20 09:02:50 -03:00
sanfordhk
1dfdf952dd 100% zh-tw translation (#3153)
* Completed zh-tw translation
2019-08-28 09:06:33 -03:00
sanfordhk
7330e4326e partial translation zh-tw update (#3148) 2019-08-26 17:41:36 -03:00
Ale Martinez
a9bbe5dc5a Use double division to compute dpi factors
Fixes #2628
2019-08-25 14:21:18 -03:00
Ale Martinez
3e99394d39 Fixed order of operations in CoreTemp calculation to match MatLab code
Fixes #2885
2019-08-24 20:52:37 -03:00
Ale Martinez
a3d1c624e4 Fixed Estimate Power not including Bike Mass on Power required to accelerate
Reported by user Steve Short at the forum
2019-08-24 20:46:08 -03:00
Marcel Breij
f6559cd181 Updated Dutch Translation 2019-08-23 10:36:59 -03:00
Ale Martinez
223cd82cdc Spanish translation - minor updates and spell checking 2019-08-22 14:52:30 -03:00
Alejandro Martinez
600a9cfb43 Add Import Chart menu to Main Window and Chart Bar (#3146)
It allows to import .gchart files from menus as an alternative
to drag&drop, for completeness and to reduce end user questions.
2019-08-22 09:52:52 -03:00
sanfordhk
1a5978ac36 partial translation zh-tw update (#3147) 2019-08-22 09:51:45 -03:00
grauser
1d6d66f960 Translation : French update (1/3) 2019-08-21 11:46:51 +02:00
grauser
937b70e596 FitRideFile : Add Powertap/Powercal and Favero 2019-08-21 11:46:31 +02:00
Alejandro Martinez
39b01c2649 Preserve UTF-8 encoding when reading namedsearches.xml config file (#3145)
Fixes #3143
2019-08-20 13:23:00 -03:00
UgoBor
e68afa6aea Edit Italian Translation GC v3.5 2019-08-20 16:14:10 +02:00
sanfordhk
ff0a75bbc6 partial translation zh-tw update (#3142)
focused on translation of main functions and main UI clean-up. default zone names translated and will work only with UTF-8 reading fix for issue #2978
2019-08-19 12:26:59 -03:00
Ale Martinez
895d0d1cb6 Updated Spanish Translation 2019-08-17 21:07:19 -03:00
sanfordhk
ea8f11ac86 partial update of zh-tw translation (#3140) 2019-08-16 07:54:28 -03:00
Ale Martinez
85f471bd68 Partial Update of Spanish Translation 2019-08-13 21:52:52 -03:00
Ale Martinez
4b8f9cc8f0 Enable translation of "Peak X" interval names from Find Intervals 2019-08-13 19:38:12 -03:00
Joern
fc20b9c4d8 Merge pull request #3137 from Joern-R/DE
Update Translation DE
2019-08-09 18:59:22 +02:00
Joern
84fbfc464c Update Translation DE 2019-08-09 15:33:46 +02:00
Alejandro Martinez
3987833102 Allow Banister to use other performance metric besides Power Index (#3136)
* 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
2019-08-04 18:01:09 -03:00
Sping Zhao
2babb9f9de zh-cn translation updated to date. (#3135) 2019-08-04 18:00:47 -03:00
gcoco
ee1d2b0ea6 Run make silently (#3133)
And force it to run again if it crashes so we can see what went wrong.
2019-07-24 16:49:46 -03:00
Ale Martinez
e1ddeffd7f Banister - fixed score accumulation for multiple activities per day
It was notable when a second activy has score=0, s.t. a transition
run, provoked the score for the day to go to zero.
2019-07-19 10:33:12 -03:00
Ale Martinez
f83a367796 CloudDB chart upload - allow digits and hyphen but not underscore in domains
Issue reported at the forum
2019-07-19 10:32:28 -03:00
Ale Martinez
dd755386d3 CloudDB chart upload - allow subdomains in email address 2019-07-18 10:36:15 -03:00
Ale Martinez
b66a668669 Fix Lap Swim from Length Data - Preserve HR data
It was discarded when present
2019-07-14 13:48:40 -03:00
Ale Martinez
e8a41b1228 Fix Speed from Distance - Raised moving average limit
To account for bad data in Open Water files
2019-07-07 19:22:19 -03:00
Mark Liversedge
7b659e69d8 Add CV alongside RMSE on CP Chart
.. seems silly to not do it, and its relatively useful when comparing
   the different model fits.
2019-07-07 13:33:17 +01:00
Ale Martinez
236f782e66 Fixed Remote Calendar authorization
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.
2019-07-04 19:33:04 -03:00
Joern
a6b7993fa5 Merge pull request #3127 from qheath/translations
Translations
2019-07-03 17:00:41 +02:00
Joern
457a92a067 Merge pull request #3129 from mtbkeith/Lezyne_SuperGPS
Add Lezyne Super GPS
2019-07-03 16:27:14 +02:00
Keith Reynolds
1e1dceef73 Add Lezyne Super GPS 2019-07-02 15:53:47 -06:00
Quentin Heath
3a57fdb8a8 french translation
use proper French instead of mimicking English
2019-07-01 09:53:14 +09:00
Quentin Heath
35db3a6f03 fix translations
replace some mistaken "Today's Plan" by the appropriate "Polar Flow"
2019-07-01 09:42:29 +09:00
Ale Martinez
494422399f Change heading for direction in Power estimators
Missing part from 9f0c70391b
2019-06-11 18:06:04 -03:00
Frank Zschockelt
1dbe3c9be8 FitRideFile: Unify handling of invalid product id 2019-06-07 20:06:09 +02:00
Benedikt Stegmaier
f334097f30 FIT : Add Hammerhead as manufacturer 2019-06-07 19:52:30 +02:00
grauser
27e044f763 Fit : Power phases - limit to 360
fix #3030
2019-06-02 22:11:34 +02:00
grauser
330b5cbe71 Translation : lupdate and french update (1/2) 2019-06-01 12:20:29 +02:00
Ale Martinez
385d5234de LTM Table - Format Pace and Best times minutes in Sexagesimal format
Same logic as LTM Plot in commit b7ced302ad
2019-05-31 23:00:23 -03:00
ericchristoffersen
6e175dfb91 Raise slope limit to +-40. (#3092) 2019-05-28 08:06:43 +01:00
Hennadiy (Gena) Verkh
70f465f914 Fix estimator not running for runs, if there are no bike rides (#3110) 2019-05-26 22:16:16 -03:00
grauser
a8ca30ccd7 FIT : Add Respiration Rate 2019-05-23 22:36:43 +02:00
grauser
44026a1838 Fit : Add some Garmin models 2019-05-23 22:22:00 +02:00
grauser
8820817d0f CSV : iBike remove debug line 2019-05-23 21:54:01 +02:00
Oleksiy Mishchenko
08a704ec1b No reason to skip a datapoint if DFPM is null 2019-05-23 21:51:59 +02:00
Oleksiy Mishchenko
fbb6f68f81 iBike CSV: If Timestamp stream is present, take the first one as the
activity start time.

It is out of sync when merged with external GPS data.
2019-05-23 21:51:59 +02:00
oleksiy
eec18940ae CSV : ibike, import recorded Air Density as Rho XDATA series
Signed-off-by: oleksiy <oleksiy@oleksiy-macbookpro3.lan>
Signed-off-by: oleksiy <amishchenko@gmail.com>
2019-05-23 21:51:59 +02:00
Ale Martinez
d2c2085741 Fixes R GC.activity when the data frames list don't match the activities list
The names attribute length must be equal to the vector size
Fixes #2542
2019-05-21 20:36:17 -03:00
Ale Martinez
9c9d1e52e9 Cosmetic change in the name of found intervals
- 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.
2019-05-21 13:15:32 -03:00
Ale Martinez
23049b4277 Changed Time in Zone counts to fix percentages aggregation
This solves the issue when activities not having all the data
channels available are aggregated.
Forces a metric recomputation to account for these changes.
2019-05-20 17:14:56 -03:00
Ale Martinez
794e097f8f Changed RideDB to save metrics with aggregateZero even when value is zero
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.
2019-05-20 17:14:56 -03:00
Alejandro Martinez
c02714ecc8 Merge pull request #3104 from jgpallero/patch-3
Update AvgLTE, AvgRTE, AvgLPS, and AvgRPS in BasicRideMetrics.cpp to fix #3102
2019-05-20 17:11:28 -03:00
Ale Martinez
9a0f291057 Added AggregateZero to Time in Zone Percentage metrics
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.
2019-05-16 22:59:43 -03:00
jgpallero
91c9d2d770 Update AvgLTE, AvgRTE, AvgLPS, and AvgRPS in BasicRideMetrics.cpp
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)
2019-05-16 16:59:41 +02:00
Alejandro Martinez
3421523768 Merge pull request #3101 from amtriathlon/master
Added Time Recording and use it for Time in Zone Percentages
2019-05-15 17:42:57 -03:00
Alejandro Martinez
f7e318e959 Merge pull request #3098 from jgpallero/patch-1
Update LeftRightBalance.cpp fixes #2955
2019-05-15 17:41:15 -03:00
Ale Martinez
75146af6fe Added Time Recording and use it for Time in Zone Percentages
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.
2019-05-14 20:50:19 -03:00
grauser
3f4b7a64e3 CSV : ibike note can have ","
fix #868
2019-05-14 22:31:51 +02:00
grauser
7cb72490a8 CVS : ibike convert temperature for english
temperature in english (imperial) ibike file is in degF
2019-05-14 22:01:13 +02:00
grauser
09acc4700e CSV : ibike change metric/imperial determination
Use info on first line
2019-05-14 21:51:19 +02:00
jgpallero
439a7f6e12 Update LeftRightBalance.cpp
Add additional checks in order to differentiate between cycling and running
2019-05-14 12:17:10 +02:00
Ale Martinez
3316f41502 Fix Lap Swim from Length - Ignore Garmin Smart Recording disabled
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
2019-05-13 21:41:53 -03:00
grauser
c45bd52edd CSV : Convert total weight to metric (if needed) 2019-05-13 22:06:11 +02:00
grauser
20d6d80ded CSV : ibike keep original weight, CdA and Crr for aerolab 2019-05-13 22:01:55 +02:00
grauser
523be2bc0a FIT : Add Lezyne Micro-GPS
Thank you Claus Assmann
2019-05-13 18:12:56 +02:00
grauser
d27b4a639b Strava : Correct commit for indoor lap.
Keep last lap seconds
2019-05-13 18:10:17 +02:00
Frank Zschockelt
73e5d0bd4d FitRideFile: Add Lezyne MegaXL 2019-05-13 08:25:35 +02:00
jgpallero
04d4403844 Update LeftRightBalance.cpp
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
2019-05-12 20:27:06 +02:00
Ale Martinez
9796d9044f RR from txt files - filter and record HR for each second
Fixes #3095
2019-05-11 21:01:29 -03:00
Ale Martinez
8c995a5339 HRV import from text file - fix discard of last line
Fixes #3094
2019-05-11 11:32:04 -03:00
Alejandro Martinez
4ca3cbcffe Merge pull request #3087 from amtriathlon/BanisterRun
Add Banister and Performance for Running Power
2019-05-04 13:41:13 -03:00
ericchristoffersen
bff9cfe1d0 Issue 3057:VirtualCalc incomplete, produces NaN (#3064) 2019-05-04 07:51:20 +01:00
grauser
72ac997a84 Interval : Add a message box "Are you sure you want to delete selected interval?" 2019-05-02 23:06:24 +02:00
grauser
7409c719b3 Strava : Correct last commit for indoor trainer ride 2019-05-02 21:52:58 +02:00
grauser
fa9d32dbf0 WorkoutWizard : Change max slope to 20%
Many new trainers can simulate slope >14% and
KICKR CLIMB max incline is 13%

fix #3082
2019-05-02 21:18:42 +02:00
grauser
c5d57af45f Strava : It seems in some case (indoor file?) we don't have start_index for laps
fix #3010
2019-05-02 17:13:10 +02:00
grauser
0e08a7b8bc ErgDB : download from ergdb.org 2019-04-30 22:05:33 +02:00
Alejandro Martinez
2987e110a2 Merge pull request #2914 from cyberfuzzie/fix-gpx-decimal
Change GPX decimal separator to dot
2019-04-27 18:29:26 -03:00
Joern
d698dbd942 Merge pull request #3090 from Joern-R/GchartImport
Chart Import Dialog
2019-04-27 19:24:26 +02:00
Joern
b743440246 Chart Import Dialog
... allow column header to get translated
2019-04-27 18:13:19 +02:00
Ale Martinez
b30497692a Fix Elevation - Add explanation to Network Error 4
Closes #3089
Closes #3068
2019-04-27 12:48:44 -03:00
Ale Martinez
27c15f9d20 Fix crash on distribution chart
close #3085
2019-04-27 12:22:31 -03:00
Ale Martinez
00aea878bd Rename Segment uses RenameIntervalDialog instead of EditIntervalDialog
Fixes #3061
2019-04-27 11:28:13 -03:00
Ale Martinez
c00efb94e5 Set sync on startup and import to false when a cloud account is deleted
Fixes #2936
2019-04-25 17:30:04 -03:00
Ale Martinez
93ec3246cf Travis-ci - change from trusty to xenial for Linux builds
Trusty reaches end of life on april 2019
2019-04-25 14:35:59 -03:00
Ale Martinez
8facce909a Add Banister and Performance for Running Power
- 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
2019-04-23 18:22:36 -03:00
Ale Martinez
44d17a606b Added PowerInWatts extension to GPX Parser
Fixes #3084
2019-04-23 12:13:30 -03:00
Alejandro Martinez
15e70f9e9d Change remaining TSS to BikeStress
Reported at the forum
2019-04-19 17:23:48 -03:00
Alejandro Martinez
009d77aa22 Merge pull request #3080 from amtriathlon/RunEstimates
Add CP Model Estimates for Running Power
2019-04-16 12:34:57 -03:00
Ale Martinez
ff0b32989f Add CP Models for Running Power
- 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
2019-04-15 15:26:35 -03:00
Mark Liversedge
fc9fb7ba24 Import Workouts from WebPageWindow
.. so we can open ergdb as a chart window and browse and
   select workouts to import.
2019-04-15 08:31:22 +01:00
riccioclista
4083be3744 xdata: Fix min/max of spinbox in xdata editor (#2995) 2019-04-15 07:46:59 +01:00
Chris Cleeland
b8c2bd35b7 Fix issue #3007 by specifying HFS+ for fs type (#3015) 2019-04-15 07:46:00 +01:00
ericchristoffersen
d20291031a Fix divide by zero in slerp, also center spline length arc points (#3072) 2019-04-15 07:44:17 +01:00
ericchristoffersen
a1f3a98f79 Issue 3065: Uncombine the printing of lat and long telemetry. (#3066) 2019-04-15 07:43:06 +01:00
ericchristoffersen
72bc73ceac Issue 3058: Buffer overrun by 1. (#3063) 2019-04-15 07:38:58 +01:00
Alejandro Martinez
41ac0dc1cd Create ISSUE_TEMPLATE.md
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.
2019-04-14 20:45:10 -03:00
Ale Martinez
e1949c59f1 Activity Manual Entry - Metadata entry fields mimic RideMetadata behavior
Changed Notes format to preserve columns and
Sport/Workout Code completers to honor retrieve previous values on "*"
2019-04-11 20:18:35 -03:00
Ale Martinez
f817692659 Pad missing altitude in FIT file records with previous value
Previous behavior is to pad with zeroes which inflates Elevation Gain
Fixes #3070
Fixes #3067
Includes test file
2019-04-05 20:48:13 -03:00
Ale Martinez
cefb1b3f12 Added Mac Preferences image for the wiki 2019-04-05 11:35:41 -03:00
Ale Martinez
f77cf6d934 Read Zones files using UTF-8 Codec
Fixes #2978 for Windows builds
2019-04-05 10:52:52 -03:00
Alejandro Martinez
7e788aa50c Added Windows High DPI Settings Image for the Wiki 2019-04-04 21:09:45 -03:00
Ale Martinez
cce26607ea FitRideFile - Rename record field 90 as PERFORMANCECONDITION
It is not docummented but it seems to match the observed values in GC
2019-03-29 19:33:52 -03:00
Alejandro Martinez
74349879b7 Merge pull request #3060 from amtriathlon/master
Additional Running Dynamics support
2019-03-29 18:17:48 -03:00
Ale Martinez
81bf4a0b48 Additional Running Dynamics support
-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
2019-03-29 17:21:32 -03:00
Alejandro Martinez
cea2c09ea6 Merge pull request #3056 from amtriathlon/master
Double-click on LTMPopup ride list selects Activity and Activities view
2019-03-25 11:51:42 -03:00
Ale Martinez
5b6c1f5a5b Travis-ci upgrade to xcode10.1 for osx builds
Fix issues building libsamplerate
2019-03-25 09:59:07 -03:00
Ale Martinez
f8d530db4c Double-click on LTMPopup ride list selects Activity and Activities view
Fixes #922
2019-03-24 19:51:16 -03:00
ericchristoffersen
8e0c303759 Teach fixgps to use cubic splines instead of linear interpolation (#3044) 2019-03-19 09:30:26 +00:00
ericchristoffersen
c299a7237e Issue 3048: Teach fix distance to use length on spline path (#3049)
* Issue 3048: Teach fix distance to use length on spline path

* Remove debug pragma
2019-03-19 09:29:50 +00:00
Mark Liversedge
681f87a432 Curve fill colored zones (AllPlot) 2/2
.. 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.
2019-03-12 22:06:45 +00:00
Mark Liversedge
d2a8951c93 Downgrade to GPL-V2 License
.. 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.
2019-03-12 19:16:22 +00:00
Mark Liversedge
95901aa1e2 Curve fill colored zones (QWT) 1/2
.. 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.
2019-03-12 18:20:32 +00:00
Ale Martinez
cae7e0b6b6 Fix vlc playback in travis-ci generated AppImage 2019-03-10 13:10:41 -03:00
Ale Martinez
9fb21af373 Enable OPENDATA for Travis-ci builds
Change OPENDATA_DISABLE and fix GC_CLOUD_OPENDATA_SECRET default
Escaping special chars with travis secure is tricky...
2019-03-08 21:25:04 -03:00
Ale Martinez
e2ff21e244 Fix Travis-ci Linux builds
Add qt59translations and use linuxdeployqt release 6
2019-03-08 18:43:31 -03:00
Ale Martinez
1c762c1d00 Add Whithings/Nokia, OpenData and SportTracks secrets for Travis-ci builds
Also removed lmfit since it is in the repo from f5055aa0e3
2019-03-08 14:42:10 -03:00
Joern
5b28c67fdf Merge pull request #3037 from Joern-R/VC2017
VC2017/Qt 5.12.1 - Fix 64Bit Build Problem
2019-03-06 14:25:42 +01:00
Joern
c9600248c6 Proper Fix for the VS2017 / Qt 5.12.x Problem
... provided by Eric
2019-03-06 12:03:15 +01:00
Joern
629a5d9446 VC2017/Qt 5.12.1 - Fix 64Bit Build Problem
... 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
2019-03-03 11:46:09 +01:00
Mark Liversedge
d93404fe77 Fixup script on Mac use backwards copatible dmg format
.. creates a JHFS+ UDBZ format DMG
2019-02-25 13:41:52 +00:00
Mark Liversedge
30e0cec696 DEVELOPMENT BUILD 1903
.. markup a new development build to get Strava fixups out.
2019-02-22 09:38:21 +00:00
grauser
030a1bee02 Strava : Use 64bit for Strava ID
fix #3019
2019-02-19 15:35:35 +01:00
Eric Christoffersen
7d2d7627ad Disable 'calculator' acting on crs_loc. 2019-02-18 15:24:15 +00:00
Eric Christoffersen
1402f6ad6a Ride GPX files in Train View
.. 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 #3021
Fixes #3024
2019-02-18 08:01:21 +00:00
Joern
356069339f Merge pull request #3018 from Joern-R/Ignore
Ignore MSVC2017 build artifacts
2019-02-10 17:29:27 +01:00
Joern
68b42549e8 Ignore MSVC2017 build artifacts 2019-02-10 16:18:51 +01:00
Joern
095344156c Merge pull request #3016 from Joern-R/DE
Translation Fix
2019-02-10 15:26:23 +01:00
Joern
a4c78a769a Translation Fix 2019-02-10 14:43:42 +01:00
riccioclista
20ffbb39f5 Prevent GC from crashing if Bindings method return NULL PythonDataSeries (#3014) 2019-02-09 09:53:31 +00:00
Mark Liversedge
8836252cdf CP plot show ride as power index
.. similar to showing as a percent of athlete best, this
   scales the ride mmp to percent of the average athlete.
2019-02-03 11:46:23 +00:00
Ale Martinez
ba8946d8bc LocationInterpolation - Fix compilation errors and warning on Linux/Mac
Errors described in https://web.archive.org/web/20130423054841/http://www.agapow.net/programming/cpp/no-arguments-that-depend-on-a-template-parameter
Warning was initialization reorder
2019-01-30 13:03:00 -03:00
Eric Christoffersen
82aff2f40a Add missing 'public' 2019-01-30 09:00:38 +00:00
Eric Christoffersen
cd9b03e484 Merge Activity by Distance
.. 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.
2019-01-29 13:59:53 +00:00
Ale Martinez
63019965b7 Change LTMPlot to use GappedCurve for Measures
Better handling when HRV data is not present
2019-01-28 16:40:16 -03:00
Mark Liversedge
9138a2890e Add Device Wizard bigger window
.. too small to cram all the devices in there now.
2019-01-27 12:59:03 +00:00
Pascal Obry
04b6bab3e5 Minor typo fixes in comment. 2019-01-27 10:25:21 +01:00
Pascal Obry
c0cf875f1b Minor typo fix. 2019-01-27 10:25:21 +01:00
grauser
80e99d1159 Fit : Be sure only on cad point used 2019-01-27 10:18:48 +01:00
grauser
3b33e65a6d translations : lupdate and update french translation 2019-01-27 10:15:32 +01:00
Hennadiy Verkh
867e86e185 Set the type of activity to Ride, Run or Swim, instead of always Ride.
If exporting a Run, use rcad instead of cad
Lrbalance was never exported - fixed it.
2019-01-27 10:13:41 +01:00
Ale Martinez
4886a8dee1 Force BikeScore to zero for runs and swims
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.
2019-01-26 20:47:09 -03:00
Ale Martinez
e8fe5906c8 Upgrade to VLC 2.2.8 for Travis-ci Linux builds 2019-01-21 14:11:07 -03:00
Ale Martinez
046840513f Upgrade Qt to 5.9.7 for Travis-ci Linux builds 2019-01-20 20:16:00 -03:00
Alejandro Martinez
543c4a6dab Merge pull request #3004 from probonopd/patch-1
Add "Categories=Science;Sports;" on the script used by Travis-ci
2019-01-19 20:28:43 -03:00
probonopd
021bbeb2fa Add "Categories=Science;Sports;" here, too
https://github.com/GoldenCheetah/GoldenCheetah/pull/3003 reloaded
2019-01-19 21:50:50 +00:00
Alejandro Martinez
993eec8946 Merge pull request #3003 from probonopd/patch-1
Add XDG categories
2019-01-19 15:14:03 -03:00
probonopd
fa4ce91b80 Add XDG categories
Sports is not a standalone category as per https://standards.freedesktop.org/menu-spec/latest/apas02.html
2019-01-19 11:38:22 +00:00
Ale Martinez
b5c9651357 Fixed Linux CI upload
linuxdeployqt changed the output name
2019-01-18 19:17:11 -03:00
Mark Liversedge
60dbc5d2e6 DEVELOPMENT BUILD 1901
.. markup a new development build.
2019-01-18 17:07:48 +00:00
Joern
b374ceb4dc Merge pull request #3000 from Joern-R/DE
Update Translation DE
2019-01-17 20:15:12 +01:00
Joern
5105669402 Merge pull request #3001 from Joern-R/FixCI
Fix Windows CI
2019-01-17 20:14:47 +01:00
Joern
dff632f7fd Fix Windows CI
... in the WinCI Configuration the Constants are not referenced through other includes
2019-01-17 19:23:49 +01:00
Joern
1042f0f5b8 Update Translation DE 2019-01-17 18:27:29 +01:00
Mark Liversedge
89068ede1e Banister datafilter
.. 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.
2019-01-16 10:41:13 +00:00
Mark Liversedge
5a66c1342a Banister fixups
.. 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.
2019-01-15 16:12:25 +00:00
Mark Liversedge
fb83864f83 Banister Windows Contiguous
.. so we compute decay on the curves in periods between
   seasons and in the future.
2019-01-15 07:43:58 +00:00
Mark Liversedge
1148e3aa69 Banister fitting windows
.. 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...
2019-01-14 10:46:54 +00:00
grauser
05a8c49053 FitRide : Correct doubled interval duration 2019-01-13 22:27:35 +01:00
grauser
1841faa596 Add media folder 2019-01-13 21:35:32 +01:00
Joern
a2fe09a65e Merge pull request #2997 from Joern-R/WithingsAgain
Re-Introduce connection to Withings
2019-01-13 19:49:11 +01:00
Mark Liversedge
68c5ded23c Enable decay adjustment in Banister Helper
.. 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.
2019-01-13 15:52:24 +00:00
Mark Liversedge
9b9b6f13fe Banister Model Helper on LTM
.. 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.
2019-01-12 20:20:54 +00:00
Joern
25f13f4683 Re-Introduce connection to Withings
... remove Nokia from Screens
... access Withings APIs
2019-01-12 19:09:27 +01:00
Hennadiy (Gena) Verkh
5022dba8f3 Allow precise adjustment of the time slider with a keyboard. (#2990) 2019-01-11 14:36:25 +00:00
Mark Liversedge
9871d1e53f Banister Data Managed in Athlete
.. so we retrieve past ones and reuse rather than refresh
   and refit every time we plot it.
2019-01-11 12:45:26 +00:00
Mark Liversedge
a205e7bb73 LTM plot banister with gapped curves
.. 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.
2019-01-10 18:34:30 +00:00
Mark Liversedge
5cc2e057c8 Fix Banister Windows Build
.. missing header.
2019-01-10 16:02:21 +00:00
Mark Liversedge
0fe714566a Banister Modeling Resources
.. references for the papers it is based upon

.. added a contributed spreadsheet implementation of Banister.
2019-01-10 15:10:11 +00:00
Mark Liversedge
2aa4779df9 Banister Modelling
.. 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.
2019-01-10 14:55:25 +00:00
grauser
c9581079da Fit : Interval use total_elapsed_time if no time info
fix #2982
2019-01-08 23:00:41 +01:00
Mark Liversedge
971cd4df4b Banister Performances Update
.. 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.
2019-01-08 14:32:31 +00:00
Mark Liversedge
cdfff8f4ed LTMPlot/Tool add banister settings
.. just the chart config, will add curve data and fitting
   code in a later commit.
2019-01-06 17:50:43 +00:00
Mark Liversedge
ae3320d2ec Show performances on LTM plot
.. show weekly best performances (ready for banister curves)
.. show performance tests (also used by banister if present)
.. can toggle which ones to show.
2019-01-05 17:38:27 +00:00
Mark Liversedge
a89607e8b5 Weekly Best Performances for Banister IR
.. extracted when resolving model estimates

.. creates a weekly best performance but only looks for efforts
   between 3 and 20 minutes.
2019-01-04 17:07:18 +00:00
Mark Liversedge
efb1a648f6 CP MMP Filter improvement
.. 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).
2019-01-04 13:27:28 +00:00
Mark Liversedge
46abc66484 Banister modeling - PowerIndex performance metric
.. 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.
2019-01-04 12:31:57 +00:00
Alejandro Martinez
b128bee62d Merge pull request #2968 from riccioclista/python_console_print_expr
PythonConsole: Print expression value when executing simple statements
2019-01-02 12:42:19 -03:00
Hennadiy Verkh
807ea685d6 Added method decodePhysiologicalMetrics to decode garmin/firstbeat specific activity metrics
Added additional metrics to the metadata.xml
2019-01-01 22:05:20 +01:00
grauser
9bb0aebe46 Add test files for Firstbeat/Garmin session metrics Pull request #2986 2019-01-01 22:02:08 +01:00
grauser
49bc27b020 RideMap : Use user custom tiles 2018-12-31 17:46:07 +01:00
Ale Martinez
1ad52086e6 Updated French Translation
Contributed by Arnaud Leclere
2018-12-31 17:32:18 +01:00
Joern
d4afe27f4e Merge pull request #2985 from Joern-R/CCResize
Column Chooser Popup - Text Length
2018-12-31 11:41:29 +01:00
Joern
ef22b59064 Column Chooser Popup - Text Length
... determine widget size for button based on text length (since fixed sizes may not fit for translated texts).
2018-12-29 19:41:30 +01:00
Ale Martinez
679a9bd7c3 Allow to select .gz files on Import
Similar to .zip files
Fixes #2969
2018-12-19 11:58:06 -03:00
Mark Liversedge
61dc7f59f8 Move Google Map API key to chart settings
.. no need to clutter up general settings
2018-12-19 13:50:25 +00:00
Mark Liversedge
8299011181 Fix compile error rDir not found
.. R support is optional, so the reference to rDir
   in cut and paste code fails if R is not enabled.
2018-12-19 13:10:01 +00:00
Mikael Grønfeldt
7cf678307e Support for x-Trainer (http://www.x-trainer.dk) added.
Committer: Mikael Grønfeldt <mikael@gronfeldt.dk>

Signed-off-by: grauser <Damien.Grauser@gmail.com>
2018-12-18 22:01:29 +01:00
grauser
e91b4e998e Sporttracks.mobi : read laps
fix #2981
2018-12-18 21:39:00 +01:00
grauser
ad46bf9b32 FIT : Add debug logs 2018-12-17 23:52:20 +01:00
grauser
39e37073ad RideMapWindow : Add running markers 2018-12-17 23:52:20 +01:00
grauser
d1f255f73d RideMapWindow : Let user with Google API key use the Google Map 2018-12-17 23:52:13 +01:00
Michael Beaulieu
ca9b5b27bb RideMapWindow: 4/4 Display interval markers and draw AvgPwr color paths on OSM 2018-12-17 23:52:12 +01:00
grauser
4eca780a57 RideMapWindow : Remove the google option
Still to do restore the drawShadedRoute (color from powerzone)
2018-12-17 23:52:12 +01:00
Joern
cc22129ae6 Merge pull request #2980 from Joern-R/GroupBy
LTM Reveal Window
2018-12-17 17:07:24 +01:00
Joern
3633a1e73e LTM Reveal Window
- avoid "cut off" text for translated period strings
2018-12-16 15:48:05 +01:00
Ale Martinez
101b82597b Fixes R issue when Home is set on Linux
name was left uninitialized when Home is specified by the user
Reported at the forum.
2018-12-13 18:47:19 -03:00
Ale Martinez
feed0c7635 Save Zones files using UTF-8 for cross platform compatibility
Fixes #2978
2018-12-13 12:01:21 -03:00
Alejandro Martinez
914531edf7 Merge pull request #2979 from MaksVasilev/master
Update Russian translation
2018-12-13 11:37:46 -03:00
Maks Vasilev
f681597a32 Update Russian translation 2018-12-13 17:26:29 +03:00
Ale Martinez
f7d2431e81 Remove references to QwtPlot3d and kQOauth
They are not used anymore
2018-12-11 14:10:53 -03:00
Ale Martinez
7073fb0d09 CP Plot Tests honor sport settings
In Activities view we filter bests (and now tests) to match the
selected activity sport.
2018-12-04 15:49:47 -03:00
Mark Liversedge
a64c6f06d6 CP Plot Tests honor filter settings
.. when finding performance tests the filter settings for the
   chart need to be honored.
2018-12-02 10:12:15 +00:00
Antonius Riha
d817541708 PythonConsole: Print expr value when executing simple statements 2018-12-01 11:20:24 +01:00
Mark Liversedge
0b4d46666d Model CP and W' decay in Morton Model
.. 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
2018-11-30 15:56:52 +00:00
Ale Martinez
1a5034514c Fixes Measures FingerPrint to detect changes in decimals
Weight updates via UI involving only decimals were undetected and not saved
2018-11-29 17:00:26 -03:00
Mark Liversedge
ea5c07db0e CP Explainer Deck Updates
.. forgot to commit earlier in the year.
2018-11-27 15:13:32 +00:00
Ale Martinez
0c668c0d0b Fixed error message in Train Library when workouts cannot be copied
The existing message is misleading and it's a source of users
complains when they have the Library set to a read only folder.
Fixes #2945
2018-11-25 20:48:56 -03:00
Ale Martinez
aae62438d3 Changed Notes to Calendar Text in LTMPopup
It shows more context information than notes and allows user customization.
2018-11-19 21:50:31 -03:00
Ale Martinez
d51080ef42 LTM Charts - Changed default precision from 0 to 1 for table view
To match the default used in LTMPlot, useful to export measures s.t. Weight.
2018-11-19 16:30:13 -03:00
Ale Martinez
3f8446b9cf Travis-ci - Added qt59networkauth-no-lgpl to Linux before_install
Trying to solve CloudDb issue
2018-11-13 21:35:08 -03:00
grauser
5ed9890149 RideMap : 3/4 draw interval on OSM 2018-11-13 23:25:39 +01:00
grauser
f6ebdeab8d Fix AeroPod : AeroPod record CdA in the HR series 2018-11-13 21:06:32 +01:00
grauser
ee5e93be43 FitRideFile: Add ibike in manu 2018-11-13 21:05:25 +01:00
grauser
a7844fb6ad CsvRideFile : ibike correct ride time for pause
add XData for calculated power
2018-11-13 21:05:25 +01:00
Mark Liversedge
5f3486ebe5 CP Plot PD Profile W/KG
.. now need to tidy up chart labels.
2018-11-13 18:48:37 +00:00
Mark Liversedge
f60e28e801 CP Plot Power Profile Lines (watts only)
.. need a follow up for w/kg
2018-11-13 17:49:49 +00:00
Alejandro Martinez
5bec0878a3 Merge pull request #2957 from amtriathlon/master
Travis-ci enable Linux build to generate AppImage
2018-11-13 11:48:47 -03:00
Ale Martinez
83d4490031 Travis-ci - Install and enable Python 3.6 and SIP on Linux builds 2018-11-12 17:34:06 -03:00
Ale Martinez
6749574600 Travis-ci enable Linux build to generate AppImage
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
2018-11-11 13:42:14 -03:00
Ale Martinez
44ea4d4dc3 Better error handling in Fix Elevation
A common error ("Gateway Timeout") is explicitly reported
On error the LUW is terminated to allow the user to undo partial changes.
2018-11-06 17:26:43 -03:00
Ale Martinez
a854b9db24 Fixed Typo in Spanish translation
Fix #2953
2018-11-06 11:11:44 -03:00
thebaron06
edb0444b9f Add support for Daum realtime devices (#2952)
* 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
2018-11-05 12:46:28 +00:00
Mark Liversedge
b5ed04b7c1 CP Plot show w/kg percentiles
.. should also add 3,7,12,20 concrete percentiles so can review
   regardless of model fit.
2018-11-03 19:21:27 +00:00
Ale Martinez
c5802596dc Remove kQOAuth from travis-ci
It was deprecated on #2881
2018-11-01 19:28:05 -03:00
Ale Martinez
acad616d12 Fixed Precision of Rest HF/LF metrics
Tipically imported values show as zero on Summary
2018-11-01 17:36:30 -03:00
Alejandro Martinez
47cb7c91ef Merge pull request #2949 from gcoco/d2xx-download
Use https for download D2XX1.2.2.dmg
Redirection was breaking the download.
2018-10-29 19:07:06 -03:00
Joern
7a3d4f45e9 Merge pull request #2948 from Joern-R/Translation-DE
Translation
2018-10-29 11:07:56 +01:00
gcoco
aead637786 Enable libusb and libusb-compat (#2950)
Re-enable libusb and libusb-compat for Travis builds
Note there is still an issue with hdiutil.
2018-10-29 08:04:11 +00:00
gcoco
af8e59eea4 Use https for download 2018-10-28 22:53:48 -04:00
Joern
9e8aa07521 Translation
- Update Translation DE
- Enable one more text for translation
2018-10-28 19:43:08 +01:00
Mark Liversedge
50f77a3391 Parameter percentile off by one
.. if you're better than 10% of folks you're not in the 10% percentile.
2018-10-27 12:31:22 +01:00
Mark Liversedge
9fb73099a9 CP Plot Percentiles for CP, W' and Pmax Estimates
.. 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.
2018-10-27 11:47:15 +01:00
Ale Martinez
5c5b4e1856 Fix CPV units in ScatterPlot
Crank length is converted to meters so CPV is computed in m/s,
but displayed in cm/s
Fixes #2942
2018-10-25 11:26:27 -03:00
Ale Martinez
4c870c7825 AppImage - added libssl.so/libcrypto.so and excluded libxcb-dri3.so.0
Fixes #2915 and #2920
2018-10-24 13:16:54 -03:00
Ale Martinez
2787870c2c CPPlot force refresh when filters change, even if Date Range is the same
Previous behavior was annoying: filters s.t. sport were not applied
until date range changed.
2018-10-23 21:03:11 -03:00
Alejandro Martinez
e032358e69 Merge pull request #2946 from ianmartin/build-without-ical
Build without ical
2018-10-21 10:55:03 -03:00
Ian Martin
2707e3b402 Only include CalDAV.h if have ical library 2018-10-20 23:08:26 +01:00
Ian Martin
3f95d11b98 Only try and build CalDAVCloud if ical is present
CalDAVCloud requires ical so do not add to build unless
ical is present.
2018-10-20 18:22:29 +01:00
Mark Liversedge
aebc5dc388 Crr and CdA Regression Explainer
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).
2018-10-06 09:44:51 +01:00
Mark Liversedge
6f59d09cb2 HiDPI: Aerolab lineedits for Cda,Crr etc
.. fixed widths needed *dpiXFactor
2018-10-05 08:36:00 +01:00
Mark Liversedge
e264405302 Fix Aerolab crash on no ride selected
.. when no ride available or last ride deleted lots of crashes. None
   of the slot functions check for null, so lots of crashes.
2018-10-04 09:58:31 +01:00
Mark Liversedge
475288d427 aerolab tests rename directory 2018-10-03 22:03:10 +01:00
Mark Liversedge
5ce7b3b054 Aerolab Test Files
Contributed by:
  * Nate Lesniewski
  * Tom Anhalt
  * Juan Benjumea
2018-10-03 18:55:57 +01:00
grauser
f7f2ca1d65 RideMapWindow : Use leaflet instead of googlemap api for OSM 2/4
Trace ride, intervals and markers
2018-10-03 13:39:00 +02:00
grauser
2068221324 Remove google.api for openstreetmap mode 1/4
This first commit breaks the openstreetmap display
2018-10-03 13:38:35 +02:00
Mark Liversedge
3c822fcc61 DEVELOPMENT RELEASE 3.5 DEV1810 2018-09-27 09:00:55 +01:00
Mark Liversedge
672a16d6fd R2 label use superscript (its squared not 2) 2018-09-25 10:38:34 +01:00
Mark Liversedge
61cf324fa7 Fix units on CP plot work/time
.. performance test markers said "Unknown" for units when
   plotting work / time.
2018-09-23 11:01:17 +01:00
Mark Liversedge
1a8f4bd177 Overview metric for HRV needs to be displayed
.. its rMSSD, without the name the value is meaningless.
2018-09-22 11:55:07 +01:00
Erik Botö
1b2ef12383 ANT: HRV measurement improvements (#2935)
Improved handling of data page 4 for ANT+ HR.
2018-09-22 11:32:31 +01:00
Mark Liversedge
322b774387 HRV R-R data in Train View 3 of 3
.. 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.
2018-09-22 11:30:51 +01:00
Mark Liversedge
332184fa92 HRV R-R data in Train View 2 of 3
.. 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
2018-09-21 19:04:49 +01:00
Mark Liversedge
3a31f5d131 HRV R-R data in Train View 1 of 3
.. 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
2018-09-20 15:48:35 +01:00
Mark Liversedge
e87d3b9dec Fix Overview Window steal focus MacOS
.. 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.
2018-09-12 08:52:34 +01:00
Mark Liversedge
143c10d9c0 CP Plot Helper Title for Work/Time
.. add "Work/Time" to model name when using an LR fit
   since we convert to joules.
2018-09-05 07:47:19 +01:00
Mark Liversedge
74fe950fc2 CP Plot Helper show model name
.. set the model overlay title to the full name of the
   model being used.
2018-09-04 21:55:51 +01:00
Mark Liversedge
dd4ff86da7 Fix last commit
.. it converted CPPlot::filterpower to work which
   of course then broke model fitting.
2018-09-01 18:53:02 +01:00
Mark Liversedge
6e91261502 CP plot filter best in Work/Time plot
.. not just when plotting power or w/kg
2018-09-01 18:22:17 +01:00
vlcvboyer
1191b8bd51 fix missing break in switch/case statement (#2918) 2018-08-29 09:52:56 +01:00
Sascha Riemer
9588c9c00b Change GPX decimal separator to dot 2018-08-27 19:19:05 +02:00
Mark Liversedge
2a6083071f LR Model Fit calculate R2
.. lots of folks understand what R2 means for a linear
   regression so calculate it alongside RMSE when we
   are performing a linear regression.
2018-08-25 07:47:23 +01:00
Mark Liversedge
9e5242a782 CP Plot fix y-axis for higher values of PMax
.. when model estimates for Pmax are higher than
   the bests data (e.g. when fitting to perf tests)
   then we need to adjust the y-axis to fit.
2018-08-23 19:33:29 +01:00
Mark Liversedge
bb4a8606a6 Add Last 24 hours to date ranges
.. particularly useful when modelling with a test protocol from a
   single ride e.g. 12-7-3 CP single session test.
2018-08-23 10:20:44 +01:00
Mark Liversedge
1721064184 CP Chart Plots the Linear Work Time Model
.. 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.
2018-08-23 09:10:32 +01:00
Ale Martinez
8b2473d715 Fixes Last 6 weeks season duration
It is current day plus 41 previous ones, like existing -x days seasons
2018-08-22 21:01:22 -03:00
Alejandro Martinez
ee966c0a76 Merge pull request #2905 from DRiKE/ifdef-fix
missing ifdef GC_HAVE_ICAL
2018-08-21 21:24:55 -03:00
Luuk Hendriks
6979d665d7 missing ifdef GC_HAVE_ICAL 2018-08-22 00:54:43 +02:00
Mark Liversedge
95fd240577 Update to commit 39269cb5ca on CP2 search intervals
.. CP2 search interval mismatch betweem gui options and
   the PDModel definitions.

.. CP2 always needs 12m+ value.
2018-08-19 19:40:10 +01:00
Mark Liversedge
8a64b65ebb Linear Regress for Work/Time Model Fit
.. 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.
2018-08-17 18:39:16 +01:00
Mark Liversedge
4f19f75ed1 Tidy Up CP Plot Overlay
.. remove FTP

.. CP first, then W' and Pmax
2018-08-17 10:15:57 +01:00
Mark Liversedge
39269cb5ca Extended CP Model Search Intervals
.. slight tweak to aerobic interval to match the 7-20min
   interval used by CP2/CP3 and to reflect best practice.
2018-08-12 15:57:41 +01:00
Mark Liversedge
9208bfa617 CP window fit options
.. 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
2018-08-12 12:27:06 +01:00
Mark Liversedge
5046fe689c Hi-DPI Interval Sidebar
.. color block.
2018-08-10 22:39:22 +01:00
Mark Liversedge
c66a9d15f6 CP Plot refresh on intervals changed
.. to account for intervals being converted to performance tests
   or vice versa.
2018-08-10 15:26:17 +01:00
Mark Liversedge
3384114bdc CP 2/3p model interval defaults
.. 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.
2018-08-09 15:59:32 +01:00
Mark Liversedge
34c402a3d2 Add LevMar lib to version dialog
.. in source tree, but may change.
2018-08-08 16:04:28 +01:00
Mark Liversedge
d9b12d63f7 Alternative Levenberg-Marquardt algorithm
.. 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/
2018-08-08 14:34:35 +01:00
Mark Liversedge
7ff5a970df Disable WS/Velo models
.. the fit is wrong and need to look at that
   more closely.

.. in the meantime disabled in CPPlot.
2018-08-07 16:23:55 +01:00
Mark Liversedge
22ce1dc041 3 Param CP model env fit settings
.. default interval settings for search were way too high !
2018-08-06 15:05:32 +01:00
Mark Liversedge
e07c8494f1 Text Labels on CP plot for Performance Tests
.. tooltips getting too tricky with so much being plotted
   and since there are so few perf tests a label should be ok.
2018-08-06 09:25:19 +01:00
Mark Liversedge
73366fd582 Add tests() data filter function
.. 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.
2018-08-06 07:48:22 +01:00
Mark Liversedge
9cedf54cd5 Performance Test Intervals Bold Text
.. in the interval sidebar.

.. maybe too subtle?
2018-08-06 00:10:19 +01:00
Mark Liversedge
5455714a47 CP Plot Performance Test Aesthetics
.. 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).
2018-08-05 23:01:42 +01:00
Mark Liversedge
3aab662642 Interval sidebar helper for performance tests
.. 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.
2018-08-05 21:55:39 +01:00
Mark Liversedge
778fa11b7b CP Model Explainer Deck
.. will maintain versions here in the GC repo.
2018-08-05 18:59:39 +01:00
Mark Liversedge
a1635f075c Support Performance Tests for watts and watts/kg
.. in the CP plot and associated modelling functions.
2018-08-05 13:15:44 +01:00
Mark Liversedge
d4cb586850 CP Chart Modelling Improvements
.. 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
2018-08-05 12:31:11 +01:00
Mark Liversedge
c79565cbdd Better CP Plot Fit Summary
.. 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.
2018-08-03 12:14:39 +01:00
Mark Liversedge
54b161261e CP plot show info about fit
.. 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.
2018-08-02 21:30:24 +01:00
Ale Martinez
beb5b376b8 Replace NP for IsoPower in DataFilter validation and syntax helpers
Issue reported at the forum
2018-07-31 13:20:10 -03:00
Mark Liversedge
1a7839d051 RideFile::watts is sufficient
.. don't need to fully quality RideFile::SeriesType::watts
2018-07-30 14:53:21 +01:00
Mark Liversedge
4437e94c9a CP fit to performances
.. 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.
2018-07-30 13:22:21 +01:00
Mark Liversedge
061df5fc8d Plot performance tests on CP chart
.. 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.
2018-07-30 11:01:21 +01:00
Mark Liversedge
649d3ee014 Fix Interval Color bug
.. 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.
2018-07-29 22:01:49 +01:00
Mark Liversedge
a45fe546f9 Mark Performance Tests
.. 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.
2018-07-29 16:08:19 +01:00
Ale Martinez
0953c0d3dc Removed local instance of SpecialFields from RideMetadata
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.
2018-07-28 18:20:40 -03:00
Ale Martinez
bbe8056c45 Add Hrv4Training sample file with 12h time format
Also fix PM times
2018-07-25 11:10:00 -03:00
Ale Martinez
4667bce7da Parse Hrv4Training files using 12hr format
Fixes #2891
2018-07-24 19:24:34 -03:00
Ale Martinez
600c416f06 Changed Hrv measures to return zero when no record for date
Fixes #2896
2018-07-23 20:16:40 -03:00
Ale Martinez
5b4e754d0a Refresh PMC data when Seasons change
To consider possible changes on Starting LTS
2018-07-23 15:35:04 -03:00
grauser
55ec3973c3 FIT : Change the time_offset reference
Bryton files were impacted

fix #2029
2018-07-17 22:21:37 +02:00
Ale Martinez
e0a4330d30 Show model parameters on CPPlot for aPower and aPowerKg
Curve fitting was already enabled but parameters were not displayed
2018-07-06 20:14:49 -03:00
Ale Martinez
28e5ef66d0 Notify when data processors are running on import
Some processors s.t. Fix Altitude can take a while and
users assume the saving hanged as reported on the forum.
2018-06-30 12:56:11 -03:00
Mark Liversedge
a86b0e9b74 Update build id for development release 2018-06-08 18:24:57 +01:00
Mark Liversedge
555ec8116c Fix Version Dialog
.. no longer need kqoauth version
.. lmfit is local and v7.0
2018-06-02 12:06:01 +01:00
Mark Liversedge
e75cc607f1 Remove QTSOAP and KQOAUTH from gcconfig.pri
.. they're not required anymore.
2018-06-02 11:13:46 +01:00
Mark Liversedge
cdd99da9c9 Deprecate KQOauth
.. 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
2018-06-02 11:01:43 +01:00
Mark Liversedge
9e21ececff Fix OAuthDialog 'code' parse url
.. 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
2018-05-31 21:13:24 +01:00
Alejandro Martinez
aad45092ae Fix Windows CI Builds
Qt 5.9.4 was replaced by Qt 5.9.5 on May 16 (https://www.appveyor.com/updates/2018/05/16/), test the change to 5.9 symlink to avoid future problems.
2018-05-30 12:40:12 -03:00
qheath
c8523a2716 various minor bugfixes + warningfixes (#2878)
* 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
2018-05-30 13:33:02 +01:00
Mark Liversedge
4bda57919c Workout Editor more complete effort search
.. 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.
2018-05-28 10:00:51 +01:00
Mark Liversedge
2b64b663e1 Workout Editor Warning use 3-param CP model
.. 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.
2018-05-27 12:45:20 +01:00
Mark Liversedge
3e417f8912 Minor LMFIT fixups
.. add the copyright and disclaimer for lmfit source
.. remove references to LMFIT from gcconfig.pri
2018-05-24 18:26:29 +01:00
Mark Liversedge
f5055aa0e3 Add LMFIT source to repo
.. 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.
2018-05-23 11:24:04 +01:00
mark-inderhees
73ef4ff03f Add telemetry for time to next erg point (#2867)
* Add telemetry for time to next erg point

* Remove nextPoint. Instead use rightPoint.
2018-05-22 07:30:18 +01:00
Mark Liversedge
ba9bab3993 Add Least-Squares fit to CP Chart - 1 of 2
.. 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)
2018-05-20 18:40:51 +01:00
Mark Liversedge
b4a6690d6b Turing SIG Talk
Make available for download.
2018-05-16 14:41:49 +01:00
Mark Liversedge
973e38b782 Train view negative watts not allowed
Fixes #2868
2018-05-16 09:32:39 +01:00
Mark Liversedge
191ca89cef User Survey
Should have placed into the repo a long time ago.
2018-05-08 22:27:24 +01:00
Ale Martinez
b274aee402 Add Peak Hr and Hr Zone Metrics
Fixes #2863
2018-05-06 19:01:17 -03:00
Ale Martinez
5c9a233e96 Changed Python XData access points for consistency
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
2018-05-05 13:09:02 -03:00
Ale Martinez
efabcf84e3 Add XData series to Python GC.activity(activity=None, join="repeat") 2018-05-05 12:29:58 -03:00
Ale Martinez
3902405feb R activityXData - no need to recompute derived series 2018-05-04 17:17:33 -03:00
Ale Martinez
434c15ad50 Add R GC.activity.xdata(name="", compare=FALSE)
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
2018-05-04 16:21:36 -03:00
Ale Martinez
e1da05d00f Python activityXdataSeries result name changed to name_series 2018-05-04 14:22:58 -03:00
Ale Martinez
119b889cb4 Add activityXdataNames(name="", activity=None)
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
2018-05-02 21:02:32 -03:00
Ale Martinez
ead2650f15 Add Python activityXdataSeries(name, series, activity)
To retrieve XData series without resampling, series can be
"secs", "km" or a valuename for the requested XData name.
Fixes #2847
2018-05-02 19:40:57 -03:00
Ale Martinez
c9d3088aa1 RChart - Run script when intervals/selections change
On Activities view, last part of #2848
2018-05-01 09:51:42 -03:00
Ale Martinez
17dbb48fc4 Add R activity.intervals
Fixes #2848
2018-04-30 23:25:30 -03:00
Ale Martinez
cba2d1122d Fix Python activityIntervals start and stop
Changed from Int to Float since they may be not integer
2018-04-30 17:20:13 -03:00
Ale Martinez
bdf88cae98 Python seasonIntervals time offset by start seconds
Fixes #2860
2018-04-30 16:59:28 -03:00
Mark Liversedge
4e3b8d0548 Merge pull request #2859 from bwalding/patch-1
Correct the link to the user list
2018-04-29 14:49:24 +01:00
Ben Walding
1e53e857aa Correct the link to the user list 2018-04-29 21:49:07 +10:00
Mark Liversedge
d7613e9cc1 Merge pull request #2858 from bwalding/raise-after-oauth
Ensure the Cloud Service wizard on top after the OAuth modal dialog closes
2018-04-29 12:40:16 +01:00
Ben Walding
cf64c25d61 Ensure the ordering of windows after the OAuth modal dialog closes 2018-04-29 21:30:18 +10:00
Mark Liversedge
ce4d3eb108 Merge pull request #2856 from bwalding/lap-distance
Add Lap Distance and Lap Distance Remaining dials and telemetry
2018-04-29 10:37:25 +01:00
Ben Walding
5a065ca07c Add Lap Distance and Lap Distance Remaining dials and telemetry 2018-04-29 14:24:13 +10:00
Ale Martinez
5ea8903edc Add Python activityIntervals
Python half of #2848
2018-04-27 21:09:35 -03:00
Ale Martinez
ab3ce3b242 Remove datafilter debug 2018-04-27 21:07:27 -03:00
Mark Liversedge
cf9de7354d Compatibility Metrics and Metric Overrides
.. 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
2018-04-25 09:56:17 +01:00
Ale Martinez
1f094f5712 Always expand lap swim Fit and Tcx files
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.
2018-04-24 13:51:14 -03:00
Mark Liversedge
eb363c3fab Fix Swim FIT parse crash
.. 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
2018-04-24 10:10:02 +01:00
Alejandro Martinez
8f0fef686b Merge pull request #2850 from amtriathlon/TriScore
TriScore - On zero fallback to TRIMP Zonal Points for HR base score
2018-04-23 20:02:38 -03:00
Ale Martinez
db6eec5029 TriScore - On zero fallback to TRIMP Zonal Points for HR base score
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.
2018-04-21 19:04:17 -03:00
Ale Martinez
55e9c5ed45 Fix copy paste error in previous commit 2018-04-20 18:46:55 -03:00
Ale Martinez
8b10ebc96e CloudDB Download - Warn the user dowloading a Python chart if Python inactive
Same logic as the one existing for R charts
2018-04-20 15:05:21 -03:00
Ale Martinez
72a78e36ce Remove references to PYTHON3_VERSION from gcconfig.pri.in
No need for it after #43d264e3cb929fb0d2094a9071c4dd67891b9613
2018-04-20 11:19:32 -03:00
Mark Liversedge
43d264e3cb PYTHON3_VERSION set from PY_MINOR_VERSION
.. so we don't have to remember !
2018-04-20 08:38:37 +01:00
Ale Martinez
9751876703 Check the python3 version used to build matches the one found at runtime
To avoid crashes on Py_Initialize when 3.6 build finds 3.5 or vice-versa
Python integration is disabled and the used is notified if it was enabled.
2018-04-19 12:40:18 -03:00
Ale Martinez
1cc8f15dba Add deploy.sh script to generate Linux AppImage
To be run after starndard Linux build
2018-04-19 12:30:49 -03:00
Ale Martinez
8a9b775ff7 Add support for ISO8601 extended date time format with milliseconds
Fixes #2750
2018-04-11 20:29:45 -03:00
616 changed files with 625981 additions and 86364 deletions

3
.gitignore vendored
View File

@@ -13,6 +13,7 @@ Makefile
*.prl
*.swp
*.user
*.AppImage
# osx noise
.DS_Store
@@ -49,4 +50,6 @@ qwt/src/Makefile.Debug
qwt/textengines/mathml/debug/
qwt/textengines/mathml/release/
build.pro.user
build.pro.user.*
doc/contrib/WASP Packet Protocol.pdf

View File

@@ -1,14 +1,19 @@
branches:
- master
language:
- objective-c
compiler:
- clang
- gcc
only:
- master
- /^[vV]\d+\.\d+(\.\d+)?(-\S*)?$/
language: cpp
cache:
directories:
- $HOME/Library/Caches/Homebrew
- qwt
- D2XX
env:
matrix:
- BRANCH=master QT=qt5 QT_PATH=qt5 WEBKIT=0
global:
- BRANCH=master
- secure: iqYW7f3//ZkMVzeCEarYn0S0DqKjFU9juBh0KF6WTlUsKX902Jtsk7dFoJlNDYBf63HLgV+wW2Hc6MxI9sGiUkom0gY9/To/aeGIJFGEX2sLm/e0Ok3qN521FA0Q/OiCFsD0RC6J+yrHxzI+rf8Z1rujceUsz2KgsrfAjYYv+BY=
- secure: C6f58PXwvvHeVOjCLbyDRjgyF0tk+bXjCNUDur8VJLhJEGNdnrt+rH+d3azYaX0n348ZnQZ14as4M4rHjN1A/3DRbdUdOS7PQZrkj/n363ck1tvYOG/tzYqkEcVoQyjIJ7ZoTuBXDQry/VJmLxQjM0glTa2upNFHMOMwqZNkF+I=
- secure: mgf181ok4rJTHxAdSaeIb/OzUx7PQc6UjJYfhJQcZDjN1Nou+Um6OHpnooMHeEq0CdGuLSiv2xVmuQnRjI5MfG5re/a3l39hSzi9tPLWi1y7uOLCtQFooJw3H+LhiKZcgAtEnkTmEhUCEu5uZ7cp4lWhrQZWCR5mCDNtJrGHjiw=
@@ -23,119 +28,31 @@ env:
- secure: QXyyyutxesRVae/WFi75dxlNw2qTyWc6WQ3vmRER9BFhlrNtt8lmE+M6ghMDOhxigzSXWxHcG9r66BLOw4DML7AXg4f3NIAIYuYQrpfsWQ1TKGC/vVvIPDlNBKL62zSOoNowjup1HfZpB575wl4JkmHjoMPDfQ4yM/JVR+MKmIM=
- secure: lefpL3SB8yN0Vn1R2e0hAFpJgFnu4rJ/vn7DucSKQvJ61K7t3LrUHFXElDQGFZMbytx4OJDeYsJtrccrIHjcsSAEIyW8TTcwn5/JopnyeQ3ukV5AYpEoQusym09XKru9E7awqvnZrXz6mdoIum5JP7+H116mPN4vsvz5nkNWxeg=
- secure: RAGPq/thN9x6STNueDbeJWGUN75OLNcUVUkLHI/eZwPrkMaiQPfxIaJ+8eO2PszDcBojw3eYVhzbRvLnLiXmHL3buwD6oXMTyYnxGzCZ61DeDQ2cQa8ynKmRim5JL3viKMqtdyasXVoGf/u0GqMsgaLcqN6e/vXuXMGu6kkUPEQ=
before_install:
## try early just to check, can delete later
- date
- brew update
- sh travis/install-qt.sh
##- brew install $QT
- brew install libical
##- brew install libusb libusb-compat # no longer needed?
- brew install srmio
- brew install libsamplerate
- rm -rf '/usr/local/include/c++'
- brew install r
- brew install brewsci/science/lmfit
## Disable KML for now
##- brew install --HEAD travis/libkml.rb
- sudo chmod -R +w /usr/local
- curl -O http://www.ftdichip.com/Drivers/D2XX/MacOSX/D2XX1.2.2.dmg
- git clone --branch 0.98 https://github.com/kypeli/kQOAuth.git kQOAuth-0.98
- cd kQOAuth-0.98
- CC=clang CXX=clang++ /usr/local/opt/$QT_PATH/bin/qmake -makefile -recursive QMAKE_CXXFLAGS_WARN_ON+="-Wno-unused-private-field -Wno-c++11-narrowing"
- CC=clang CXX=clang++ make -j2 qmake_all
- CC=clang CXX=clang++ sudo make install
- cd ..
- hdiutil mount D2XX1.2.2.dmg
before_script:
- mkdir D2XX
- cp /Volumes/release/D2XX/Object/10.5-10.7/x86_64/libftd2xx.1.2.2.dylib D2XX
- sudo cp /Volumes/release/D2XX/Object/10.5-10.7/x86_64/libftd2xx.1.2.2.dylib /usr/local/lib
- cp /Volumes/release/D2XX/bin/*.h D2XX
- sed -i "" "s|libftd2xx.dylib|@executable_path/../Frameworks/libftd2xx.1.2.2.dylib|"
src/FileIO/D2XX.cpp
- cp qwt/qwtconfig.pri.in qwt/qwtconfig.pri
- cp src/gcconfig.pri.in src/gcconfig.pri
- /usr/local/opt/$QT_PATH/bin/lupdate src/src.pro
- if [[ "$WEBKIT" == "0" ]]; then echo DEFINES += NOWEBKIT >> src/gcconfig.pri; fi
- sed -i "" "s|#\(CONFIG += release.*\)|\1 static |" src/gcconfig.pri
- sed -i "" "s|#\(QMAKE_LRELEASE\).*|\1 += /usr/local/opt/$QT_PATH/bin/lrelease|"
src/gcconfig.pri
- sed -i "" "s|#\(QMAKE_CXXFLAGS\).*|\1_RELEASE += -mmacosx-version-min=10.7 -arch
x86_64|" src/gcconfig.pri
- sed -i "" "s|^#CloudDB|CloudDB|" src/gcconfig.pri
- sed -i "" "s|^#LIBZ|LIBZ|" src/gcconfig.pri
- sed -i "" "s|#\(SRMIO_INSTALL =.*\)|\1 /usr/local|" src/gcconfig.pri
- sed -i "" "s|#\(D2XX_INCLUDE =.*\)|\1 ../D2XX|" src/gcconfig.pri
- sed -i "" "s|#\(D2XX_LIBS =.*\)|\1 -L../D2XX -lftd2xx.1.2.2|" src/gcconfig.pri
- sed -i "" "s|#\(KQOAUTH_INSTALL =.*\)|\1 /usr/local|" src/gcconfig.pri
- sed -i "" "s|#\(KQOAUTH_INCLUDE =.*\)|\1 \$\$[QT_INSTALL_LIBS]/kqoauth.framework/Headers|"
src/gcconfig.pri
- sed -i "" "s|#\(KQOAUTH_LIBS =.*\)|\1 -F\$\$[QT_INSTALL_LIBS] -framework kqoauth|"
src/gcconfig.pri
## Disable KML for now
#- sed -i "" "s|#\(KML_INSTALL =\).*|\1 /usr/local|" src/gcconfig.pri
#- sed -i "" "s|#\(KML_LIBS =.*\)|\1 -L/usr/local/lib -lkmlxsd -lkmlregionator -lkmldom -lkmlconvenience -lkmlengine -lkmlbase -lexpect|" src/gcconfig.pri
- sed -i "" "s|#\(ICAL_INSTALL =.*\)|\1 /usr/local|" src/gcconfig.pri
- sed -i "" "s|#\(ICAL_LIBS =.*\)|\1 -L/usr/local/lib -lical|" src/gcconfig.pri
- sed -i "" "s|#\(LIBUSB_INSTALL =\).*|\1 /usr/local|" src/gcconfig.pri
- sed -i "" "s|#\(LIBUSB_LIBS =.*\)|\1 -L/usr/local/lib -lusb -lusb-1.0|" src/gcconfig.pri
- sed -i "" "s|#\(SAMPLERATE_INSTALL =\).*|\1 /usr/local|" src/gcconfig.pri
- sed -i "" "s|#\(SAMPLERATE_LIBS =\).*|\1 -L/usr/local/lib -lsamplerate|" src/gcconfig.pri
- sed -i "" "s|#\(LMFIT_INSTALL =\).*|\1 /usr/local|" src/gcconfig.pri
- sed -i "" "s|#\(DEFINES += GC_HAVE_LION*\)|\1|" src/gcconfig.pri
- sed -i "" "s|#\(HTPATH = ../httpserver.*\)|\1 |" src/gcconfig.pri
- sed -i "" "s|#\(DEFINES += GC_WANT_ROBOT.*\)|\1 |" src/gcconfig.pri
##- sed -i "" "s|\(DEFINES += GC_VIDEO_NONE.*\)|#\1 |" src/gcconfig.pri ## we want this for now XXX till AVKit fixup
##- sed -i "" "s|#\(DEFINES += GC_VIDEO_QUICKTIME.*\)|\1 |" src/gcconfig.pri ## QT is deprecated, don't build with it.
##Issues with c++11 and stdlib on travis and dependencies
- sed -i "" "s|#\(DEFINES += GC_WANT_R.*\)|\1 |" src/gcconfig.pri
- echo "QMAKE_CFLAGS_RELEASE += -mmacosx-version-min=10.7 -arch x86_64" >> src/gcconfig.pri
- sed -i "" "s/__GC_GOOGLE_CALENDAR_CLIENT_SECRET__/"$GC_GOOGLE_CALENDAR_CLIENT_SECRET"/" src/Core/Secrets.h
- sed -i "" "s/__GC_STRAVA_CLIENT_SECRET__/"$GC_STRAVA_CLIENT_SECRET"/" src/Core/Secrets.h
- sed -i "" "s/__GC_DROPBOX_CLIENT_SECRET__/"$GC_DROPBOX_CLIENT_SECRET"/" src/Core/Secrets.h
- sed -i "" "s/__GC_CYCLINGANALYTICS_CLIENT_SECRET__/"$GC_CYCLINGANALYTICS_CLIENT_SECRET"/" src/Core/Secrets.h
- sed -i "" "s/__GC_TWITTER_CONSUMER_SECRET__/"$GC_TWITTER_CONSUMER_SECRET"/" src/Core/Secrets.h
- sed -i "" "s/__GC_DROPBOX_CLIENT_ID__/"$GC_DROPBOX_CLIENT_ID"/" src/Core/Secrets.h
- sed -i "" "s/__GC_MAPQUESTAPI_KEY__/"$GC_MAPQUESTAPI_KEY"/" src/Core/Secrets.h
- sed -i "" "s/__GC_CLOUD_DB_BASIC_AUTH__/"$GC_CLOUD_DB_BASIC_AUTH"/" src/Core/Secrets.h
- sed -i "" "s/__GC_CLOUD_DB_APP_NAME__/"$GC_CLOUD_DB_APP_NAME"/" src/Core/Secrets.h
- sed -i "" "s/__GC_GOOGLE_DRIVE_CLIENT_ID__/"$GC_GOOGLE_DRIVE_CLIENT_ID"/" src/Core/Secrets.h
- sed -i "" "s/__GC_GOOGLE_DRIVE_CLIENT_SECRET__/"$GC_GOOGLE_DRIVE_CLIENT_SECRET"/" src/Core/Secrets.h
- sed -i "" "s/__GC_GOOGLE_DRIVE_API_KEY__/"$GC_GOOGLE_DRIVE_API_KEY"/" src/Core/Secrets.h
- sed -i "" "s/__GC_TODAYSPLAN_CLIENT_SECRET__/"$GC_TODAYSPLAN_CLIENT_SECRET"/" src/Core/Secrets.h
- cat src/gcconfig.pri
script:
- CC=clang CXX=clang++ /usr/local/opt/$QT_PATH/bin/qmake -makefile -recursive QMAKE_CXXFLAGS_WARN_ON+="-Wno-unused-private-field -Wno-c++11-narrowing"
- CC=clang CXX=clang++ make qmake_all
- CC=clang CXX=clang++ make -j4 sub-qwt --silent
- CC=clang CXX=clang++ make -j4 sub-src
after_success:
- cd src
- echo "Checking GoldenCheetah.app can execute"
- GoldenCheetah.app/Contents/MacOS/GoldenCheetah --help
- echo "About to create dmg file and fix up"
- /usr/local/opt/$QT_PATH/bin/macdeployqt GoldenCheetah.app -verbose=2 -dmg
- python ../travis/macdeployqtfix.py GoldenCheetah.app /usr/local/opt/$QT_PATH
- echo "Cleaning up installed QT libraries from $QT"
- brew remove $QT
- echo "Renaming dmg file to branch and build number ready for deploy"
- export FINAL_NAME=dev-prerelease-branch-master-build-${TRAVIS_BUILD_NUMBER}.dmg
- mv GoldenCheetah.dmg $FINAL_NAME
- ls -l $FINAL_NAME
- echo "Mounting dmg file and testing it can execute"
- hdiutil mount $FINAL_NAME
- cd /Volumes/GoldenCheetah
- GoldenCheetah.app/Contents/MacOS/GoldenCheetah --help
- echo "Make sure we are back in the Travis build directory"
- cd $TRAVIS_BUILD_DIR
deploy:
provider: releases
api_key:
secure: KlfkRM8oGP02y5LhbdxetnhqUG3YzVylvyhT8BTYjdoJtkJr7YXYpdhj9byZ9aiy1gSWI/g7A1X6/P8/McqRtgt4dEYr4Zg8QO7Y7QdTpgNQEwu8ZrkyyG/7b/rSkfFHDjrOAHslLVXuBNwWgi8YW1aTn0rY2AqDbOri7u6tt9Q=
file: src/$FINAL_NAME
skip_cleanup: true
on:
tags: true
repo: GoldenCheetah/GoldenCheetah
- secure: Lydms45scczE9gZvkWze2fXVbEInKW48DOCIRJWziEzxKkvXUE7WPy74fLvfvL+0JW0LH/ZLZ9EbgHcJAYYs8CBrfAeOOtnyo2DZ0ouEO13RmomSZneEKSpJxRtErcPIu+B0LzcEGyAgf7bxPVevEte50CK0pZJ7z7bHMhU23pY=
- secure: cc0pAJjkmFNw2bO3zVACmtyHTwINAHALrtUxi+nRD+FhOO9KxuxuuwvcKCZKfp9EUOjz5PrYWKV1ZH/zt/jMix8A4Gyue2mWX8WYih7aTmJBcJWsFNTCybnClreKBCh18kHdWWhkmhk8EMINDvlqxzJZGpcNO04gxhL9wuLLrNQ=
- secure: em0xXIm69rMHsHXYQiizeJB7dEFBkX33PsWDHwBNrX6lFBued23eL96KJC4RVbk6A+AHFtXFATrreZ14D5JH/E/37CXhe3X2R93WqiPUSH0s7NI4fFA1BroKUNAlqO4bMqDBidtNmwMPaLTXjaOnOZyvbAG7z+QV3TKC8tOeZDU=
- secure: VFaSERlgsjzjiDQhKw8XFvQrjdvFzHHL7V3NQg+RfELHoT6I1pAGFdl/+lRBIVOiVkbQ6XnpBA28nlf0QydPHElRZdqmh0azQV/bkUXD4ffPE8q0iSqeqhAZ+5L05K5K+Gby/y8TZE4FX6e/7trFL7oq+h9x0gq5RQO8rAcTV84=
jobs:
include:
- os: osx
osx_image: xcode10.1
compiler: clang
- os: linux
dist: xenial
compiler: gcc
before_install:
- travis/$TRAVIS_OS_NAME/before_install.sh
before_script:
- travis/$TRAVIS_OS_NAME/before_script.sh
script:
- travis/$TRAVIS_OS_NAME/script.sh
before_cache:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew cleanup; fi
after_success:
- travis/$TRAVIS_OS_NAME/after_success.sh

View File

@@ -2,7 +2,7 @@
#### **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?**

873
COPYING
View File

@@ -1,622 +1,281 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Version 2, June 1991
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
13. Use with the GNU Affero General Public License.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
14. Revised Versions of this License.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
NO WARRANTY
15. Disclaimer of Warranty.
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
@@ -628,15 +287,15 @@ free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -644,32 +303,38 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@@ -1,3 +1,12 @@
Update Note: to build GoldenCheetah v3.6 we are using the APT Package
Manager to install dependencies, including Qt and GSL, on Travis-ci
Ubuntu Xenial build environment.
You can check the travis/linux folder for the complete and updated build scripts,
the minimum Qt version known to work is 5.13 with Qt WebEngine and Qt Charts.
GSL - GNU Scientific Library is a mandatory dependency starting with v3.6
Ale Martinez - May, 2020
+++++++++++++++++++++++
LINUX BUILD WALKTHROUGH
+++++++++++++++++++++++
@@ -21,7 +30,6 @@ CONTENTS
- FTDI D2XX
- SRMIO
- liboauth
- QwtPlot3d
- libkml
3. ADDING OPTIONAL DEPENDENCIES WHEN BUILDING VERSION 3
@@ -43,7 +51,7 @@ login and open a terminal to get a shell prompt
Download MANDATORY DEPENDENCIES (browser)
-----------------------------------------
Download and install the Qt SDK from http://qt-project.org/
Once that is completed test qmake is ok with: qmake --version (should report 4.7.0 or higher)
Once that is completed test qmake is ok with: qmake --version (should report 4.9.8 or higher)
DEBIAN-BASED DISTRIBUTION INSTRUCTIONS
@@ -92,6 +100,20 @@ $ make clean
$ qmake
$ make
To compile translation you need QT tool - lrelease
If it is not found using he defaults in src/src.pro then set the full path and filename in gcconfig.pri
QMAKE_LRELEASE = /usr/bin/lrelease
When build first time you get number of error messages on .qm files missing:
"RCC: Error in 'Resources/application.qrc': Cannot find file 'translations/gc_fr.qm'"
You can ignore these messages for your build. The .qm files will be created during the
build at a later point in time via the "lrelease" command you configured in gcconfig.pri)
If your QT build includes its own local compress libs then you should comment the line below in gcconfig.pri,
otherwise you will need to have the compress libraries installed separately.
#LIBZ_INCLUDE =
#LIBZ_LIBS = -lz
You will now have a release3 binary but with none of the release3 dependencies compiled in.
Get latest GOLDEN CHEETAH source files
--------------------------------------
@@ -193,96 +215,6 @@ $ make
You now have SRM support built in.
OAUTH/CRYPT - For Tweet my ride (twitter) support
-------------------------------------------------
You should be able to install liboauth and dependencies
directly with:
$ sudo apt-get install liboauth-dev
If this does not work then:
Download the source from: http://sourceforge.net/projects/liboauth/files/liboauth-0.9.4.tar.gz/download and
unpack it into ~/Projects/liboauth-0.9.4 using archive manager
$ cd ~/Projects/liboauth-0.9.4
You may find that libcurl is not installed (which liboauth depends upon) so download it
from http://curl.haxx.se/download/curl-7.21.6.tar.gz and unpack it into ~/Projects/curl-7.21.6
using archive manager to drag and drop into your Projects folder
$ cd ~/Projects/curl-7.21.6
$ ./configure
$ make
$ sudo make install
You should now have libcurl and friends installed in /usr/local
You may find that liboauth also requires the openssl libs installed, these are available
pre-packaged thankfully so:
$ sudo apt-get install libssl-dev
This will also install zlibg which liboauth also desires.
$ cd ~/Projects/liboauth-0.9.4
$ ./configure
$ make
$ sudo make install
Now we have liboauth and libcurl in /usr/local and libssl in /usr/lib, so we can go back to
GoldenCheetah and update the gcconfig.pri to point at the right places:
$ cd ~/Projects/Live/GoldenCheetah/src
$ vi gcconfig.pri
Make sure the following are set:
LIBOAUTH_INSTALL = /usr/local
LIBCRYPTO_INSTALL = -lcrypto
LIBCURL_INSTALL=-lcurl
Make clean is needed if you have previously built, since source files examine #defines before
including this feature. You can skip it if you know why ;)
$ make clean
$ qmake
$ make
You can now tweet your rides and amaze your friends, or alternatively tweet your rides but
omit to mention average power to hide your weaknesses.
LIBQWTPLOT3D - For 3D plot
--------------------------
Download the tarball from http://qwtplot3d.svn.sourceforge.net/viewvc/qwtplot3d/branches/maintain_0_2_x/qwtplot3d/?view=tar
and unarchive it into your Projects directory using archive manager. There is no version number it just creates a
subdirectory called qwtplot3d
You will need to install libgl and extensions, this can be done with;
$ sudo apt-get install libgl1-mesa-dev
$ sudo apt-get install libglu-dev
On Ubuntu 12.10 I also ran
$ sudo apt-get install freeglut3 freeglut3-dev
$ cd ~/Projects/qwtplot3d
Edit the qwtplot3d.pri and add
CONFIG += staticlib
You will find that on modern Linuxes you also need to fix include/qwt3d_global.h by adding the line:
#include <GL/glu.h>
then build
$ qmake
$ make
Then to let gc know where the qwtplot3d libs are you need to edit gcconfig.pri;
$ cd ~/Projects/Live/GoldenCheetah/src
$ vi gcconfig.pri
And uncomment the following line and set the install directory to where you build
QWT3D_INSTALL = ~/Projects/qwtplot3d
LIBKML - For export to Google Earth
-----------------------------------

View File

@@ -1,3 +1,12 @@
Update Note: to build GoldenCheetah v3.6 we are using the Homebrew Package
Manager to install dependencies, including Qt and GSL, on Travis-ci
macOS High Sierra build environment.
You can check the travis/osx folder for the complete and updated build scripts,
the minimum Qt version known to work is 5.13 with Qt WebEngine and Qt Charts.
GSL - GNU Scientific Library is a mandatory dependency starting with v3.6
Ale Martinez - May, 2020
+++++++++++++++++++++++
MAC OSX BUILD WALKTHROUGH
+++++++++++++++++++++++
@@ -20,8 +29,6 @@ CONTENTS
2. ADDING OPTIONAL DEPENDENCIES
- FTDI D2XX
- SRMIO
- kQOAuth
- QwtPlot3d
- libkml
- libusb
- libical
@@ -210,6 +217,11 @@ $ cd .. #this should put you in the top level dir containing this file
$ qmake -recursive
$ make
When build first time you get number of error messages on .qm files missing:
"RCC: Error in 'Resources/application.qrc': Cannot find file 'translations/gc_fr.qm'"
You can ignore these messages for your build. The .qm files will be created during the
build at a later point in time via the "lrelease" command you configured in gcconfig.pri)
If make fails to find a Makefile then qmake is configured, by default, to create
an xcode project file. You will need to change the qmake command above to tell it
to create a makefile with the following:
@@ -238,8 +250,6 @@ $ open src/GoldenCheetah.app
===============================
- SRMIO
- kQOAuth
- QwtPlot3d
- libkml
- libusb
- libical
@@ -255,24 +265,7 @@ should be taken into account.
SRMIO (git)
./configure CFLAGS="-isysroot /Developer/SDKs/MacOSX10.7.sdk -arch x86_64" CPPFLAGS=-I/usr/local/D2XX/ --disable-dependency-tracking
2.2 kQOAuth - For OAuth Authentication
--------------------------------------
kQOauth (0.98)
qmake
2.3 QwtPlot3d - For 3d plot support
-----------------------------------
qwtplot3d (maintain_0_2_x)
Add the following to qwtplot3d.pro:
CONFIG += x86_64 static
QMAKE_MAC_SDK=/Developer/SDKs/MacOSX10.7.sdk
2.4 libkml - For export to Google Earth
2.2 libkml - For export to Google Earth
---------------------------------------
expat (2.0.1)
@@ -284,7 +277,7 @@ libkml (pulled down from the svn repo)
note: the added CXXFLAGS helped clear the -Werror flag that stopped compilation.
2.5 libusb - For Garmin USB2 stick support
2.3 libusb - For Garmin USB2 stick support
------------------------------------------
libusb (0.1.12)
@@ -301,7 +294,7 @@ make install
note: that the sed line updates some commands in libtool. not sure why the arch clags are not getting passed.
2.6 libical
2.4 libical
-----------
libical (0.46)

View File

@@ -1,4 +1,11 @@
Update Note: to build GoldenCheetah v3.6 we are using Microsoft Visual C++ 2017,
included in Microsoft Visual Studio 2019, with pre-installed Qt and GSL
insalled with vcpkg, on AppVeyor continuous integration platform.
You can check the appveyor.yml for the complete and updated build script,
the minimum Qt version known to work is 5.13 with Qt WebEngine and Qt Charts.
GSL - GNU Scientific Library is a mandatory dependency starting with v3.6
Ale Martinez - May, 2020
+++++++++++++++++++++++
WIN32 BUILD WALKTHROUGH
+++++++++++++++++++++++
@@ -7,6 +14,7 @@
February 2017
This instruction will guide you through a standard build of GoldenCheetah (without external
dependencies or API based services included).
@@ -157,12 +165,6 @@ Info: I plan to provide a pre-compiled set of the dependencies for the Windows v
The version currently used is: "CDM v2.10.00 WHQL Certified" - while there are more recent
version available for download.
- Qt Oauth library - kQoAuth
-- Is part of the official build as a .dll - build is done with Qt - the build uses Release 0.98
- Qt 3D plotting - qwtplot3d
-- Is part of the official build as a static lib - build is done with Qt - the build uses Release 0.3.0
- Google Earth .kml files (export)
-- Is part of the official build as a static lib - build is done with MSVC2015 - the build uses Release 1.2
(path of source code has changed to https://github.com/google/libkml)
@@ -185,7 +187,7 @@ Info: I plan to provide a pre-compiled set of the dependencies for the Windows v
Building with integration to external services (via APIs)
As of today a number of integrations with external services like Twitter, Strava, Cyclinganalytics,
As of today a number of integrations with external services like Strava, Cyclinganalytics,
Google Calendar, Dropbox, Today's Plan, Google Drive, CloudDB) exist in the official GoldenCheetah
builds. The permission to use API's of such services requires a dedicated registration (in this case
for "GoldenCheetah" as the consumer of the services) where in return the GoldenCheetah team get's
@@ -205,10 +207,3 @@ to contribute is to provide a pull-request.
Cheers.
Joern

1
ISSUE_TEMPLATE.md Normal file
View File

@@ -0,0 +1 @@
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.

View File

@@ -29,7 +29,7 @@ INSTALL-LINUX For building on Linux
INSTALL-MAC For building on Apple OS X
OSX: [![Build Status](https://travis-ci.org/GoldenCheetah/GoldenCheetah.svg?branch=master)](https://travis-ci.org/GoldenCheetah/GoldenCheetah)
macOS and Linux: [![Build Status](https://travis-ci.org/GoldenCheetah/GoldenCheetah.svg?branch=master)](https://travis-ci.org/GoldenCheetah/GoldenCheetah)
Windows: [![Build status](https://ci.appveyor.com/api/projects/status/i6dwn4m8oyu52ihi?svg=true)](https://ci.appveyor.com/project/Joern-R/goldencheetah-knhd8)

View File

@@ -1,32 +1,213 @@
version: ci.{build}
image: Visual Studio 2015
image: Visual Studio 2019
clone_depth: 1
environment:
GC_GOOGLE_CALENDAR_CLIENT_SECRET:
secure: hwjHTrSAMEbKd9PA+5x/zI4x5Uk4KQm1hdfZzkwiu8k=
GC_GOOGLE_DRIVE_CLIENT_ID:
secure: mNqG+pqpMl21ZFVvAMKvhm2rfOdv42fFpnLwfrvX5QqpWVcHEeBuUFeJeUAZfTR0GQGfWfPOEmhb9CG0W1ZJ05TIyb+kTLrWF7iijCiVR6s=
GC_GOOGLE_DRIVE_CLIENT_SECRET:
secure: T+BaB/L7x4dPPf592e0kfw4sTlAslUXl10irJqiUjpY=
GC_GOOGLE_DRIVE_API_KEY:
secure: oxTAhK/kiLUsXdYvITAgzSqeB5FRcL+XANFuAYpoW5P/xBb7XaLbNnL2gyrmzQeG
GC_CLOUD_OPENDATA_SECRET:
secure: 6fPhBiHKvJeOMqXdHGqpkPS+NpUDMczEXjedx8GcjbHr82ISX+gwSuXfOUDLq/S9
GC_WITHINGS_CONSUMER_SECRET:
secure: 86xAkdoQB8mLXq964/lGCp3ElTSF4k3a27R3UUXt3618guWLyBfsEK5Q0+XSOI3Q38w80CTpmNdwejoISv8Ilg==
GC_NOKIA_CLIENT_SECRET:
secure: pvPWraDplrKeRNamt5MKga8fzDmI2+zgFx+y3lsQE6gmBadZU2xkTIc/xCaP7UPv2erNCmKivfMOh2NIcRmqvIHynDoifNVy2P61KyG5v3E=
GC_DROPBOX_CLIENT_SECRET:
secure: 7pCVnVEKKmSU4SZN6IFqUw==
GC_STRAVA_CLIENT_SECRET:
secure: n3cMS1yy709xhSnTeWABMsoAIkJzy5euh3Pw4ehv0BzszJKoWkypF0cyW8RXSm3M
GC_TODAYSPLAN_CLIENT_SECRET:
secure: 7PnFB8cfahFT6LyP64eB7N1vkbwVaULpB2ORmEkn+J75zNB1xxGClFNXSHZ7kXhB
GC_CYCLINGANALYTICS_CLIENT_SECRET:
secure: UY+m3YypNNLUzKyGdrLw8xdCvxuQWRZi9EHS3j1ubLC4qyRL7iEVW6ubumfdh6gT
GC_CLOUD_DB_BASIC_AUTH:
secure: OEBetrOnXjsY7wN8hYqmMj6482oDORmAmCq8PI7mfnfiWE6Z4jB676JvgdNlP98q
GC_CLOUD_DB_APP_NAME:
secure: bpkyuw/BsJw0OrpuBqQwZ46CHbhkbmcjcMttVtfJoZU=
GC_POLARFLOW_CLIENT_SECRET:
secure: h2JdlC1i4QOmwpkz+Xxbrw==
GC_SPORTTRACKS_CLIENT_SECRET:
secure: n6a8nJgqMyg+VsVeoIIR8TFzxyDFVi2w/ggetQk5agY=
init:
# Setup QT 5.9.4 - 64Bit
- set QTDIR=C:\Qt\5.9.4\msvc2015_64
# Setup QT 5.14 - 64Bit
- set QTDIR=C:\Qt\5.14\msvc2017_64
- set PATH=%QTDIR%\bin;%PATH%
- qmake --version
# Setup MSVC - VS 2015
# Setup MSVC - VS 2019
- call c:\"Program Files (x86)"\"Microsoft Visual Studio"\2019\Community\VC\Auxiliary\Build\vcvarsall.bat amd64
- CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
# Setup NSIS
- set PATH=%PATH%;C:\"Program Files (x86)"\NSIS
# Get the libraries
- ps: Start-FileDownload 'https://github.com/Joern-R/gc-ci-libs/releases/download/0.0.2/gc-ci-libs.zip' -Filename 'c:/gc-ci-libs.zip'
- 7z x c:/gc-ci-libs.zip -oC:\libs
cache:
- gc-ci-libs.zip
- jom_1_1_3.zip
- sip-4.19.8.zip
- C:\R
- C:\Python -> src\Python\requirements.txt
- c:\tools\vcpkg\installed\
- qwt
install:
# choco install winflexbison
# Get the libraries
- if not exist gc-ci-libs.zip appveyor DownloadFile "https://github.com/GoldenCheetah/WindowsSDK/releases/download/v0.1.1/gc-ci-libs.zip"
- 7z x -y gc-ci-libs.zip -oC:\libs
# GSL
- vcpkg install gsl:x64-windows
# Get config
- copy qwt\qwtconfig.pri.in qwt\qwtconfig.pri
- copy c:\libs\gcconfig64-Release.appveyor.pri src\gcconfig.pri
# Get jom
- if not exist jom_1_1_3.zip appveyor DownloadFile "https://download.qt.io/official_releases/jom/jom_1_1_3.zip"
- 7z x -y jom_1_1_3.zip -oc:\jom\
- set PATH=%PATH%;c:\jom\;
# Get R and add to config
- ps: >-
if (-not (Test-Path 'C:\R')) {
$rurl = $(ConvertFrom-JSON $(Invoke-WebRequest https://rversions.r-pkg.org/r-release-win).Content).URL
Start-FileDownload $rurl "R-win.exe"
Start-Process -FilePath .\R-win.exe -ArgumentList "/VERYSILENT /DIR=C:\R" -NoNewWindow -Wait
}
- set PATH=%PATH%;c:\R\bin\;
- R --version
- echo DEFINES+=GC_WANT_R >> src\gcconfig.pri
# Get Python embeddable and install packages
- ps: >-
if (-not (Test-Path 'C:\Python')) {
Start-FileDownload "https://www.python.org/ftp/python/3.7.7/python-3.7.7-embed-amd64.zip" Python.zip
7z x Python.zip -oC:\Python\
echo python37.zip . '' 'import site' | Out-File C:\Python\python37._pth -Encoding ascii
mkdir C:\Python\lib\site-packages
c:\python37-x64\python -m pip install --upgrade pip
c:\python37-x64\python -m pip install -r src\Python\requirements.txt -t C:\Python\lib\site-packages
}
# Get SIP and and install on Python
- c:\python37-x64\python --version
- if not exist sip-4.19.8.zip appveyor DownloadFile "https://sourceforge.net/projects/pyqt/files/sip/sip-4.19.8/sip-4.19.8.zip"
- 7z x sip-4.19.8.zip
- cd sip-4.19.8
- c:\python37-x64\python configure.py
- jom -j4
- nmake install
- cd ..
# Add Python (avoiding colision between GC Context.h and Python context.h)
- echo DEFINES+=GC_WANT_PYTHON >> src\gcconfig.pri
- echo PYTHONINCLUDES=-ICore -I\"c:\python37-x64\include\" >> src\gcconfig.pri
- echo PYTHONLIBS=-L\"c:\python37-x64\libs\" -lpython37 >> src\gcconfig.pri
# GSL
- echo GSL_INCLUDES=c:\tools\vcpkg\installed\x64-windows\include >> src\gcconfig.pri
- echo GSL_LIBS=-Lc:\tools\vcpkg\installed\x64-windows\lib -lgsl -lgslcblas >> src\gcconfig.pri
before_build:
# Define GC version string, only for tagged builds
- if %APPVEYOR_REPO_TAG% == "true" (echo DEFINES+=GC_VERSION=VERSION_STRING >> src/gcconfig.pri)
# Enable CloudDB
- echo CloudDB=active >> src\gcconfig.pri
# Add Train Robot
- echo DEFINES+=GC_WANT_ROBOT >> src\gcconfig.pri
# Add debug console
#- echo CONFIG+=console >> src\gcconfig.pri
# Patch Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_GOOGLE_CALENDAR_CLIENT_SECRET__', $env:GC_GOOGLE_CALENDAR_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_GOOGLE_DRIVE_CLIENT_ID__', $env:GC_GOOGLE_DRIVE_CLIENT_ID | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_GOOGLE_DRIVE_CLIENT_SECRET__', $env:GC_GOOGLE_DRIVE_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_GOOGLE_DRIVE_API_KEY__', $env:GC_GOOGLE_DRIVE_API_KEY | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace 'OPENDATA_DISABLE', 'OPENDATA_ENABLE' | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_CLOUD_OPENDATA_SECRET__', $env:GC_CLOUD_OPENDATA_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_WITHINGS_CONSUMER_SECRET__', $env:GC_WITHINGS_CONSUMER_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_NOKIA_CLIENT_SECRET__', $env:GC_NOKIA_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_DROPBOX_CLIENT_SECRET__', $env:GC_DROPBOX_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_STRAVA_CLIENT_SECRET__', $env:GC_STRAVA_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_TODAYSPLAN_CLIENT_SECRET__', $env:GC_TODAYSPLAN_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_CYCLINGANALYTICS_CLIENT_SECRET__', $env:GC_CYCLINGANALYTICS_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_CLOUD_DB_BASIC_AUTH__', $env:GC_CLOUD_DB_BASIC_AUTH | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_CLOUD_DB_APP_NAME__', $env:GC_CLOUD_DB_APP_NAME | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_POLARFLOW_CLIENT_SECRET__', $env:GC_POLARFLOW_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_SPORTTRACKS_CLIENT_SECRET__', $env:GC_SPORTTRACKS_CLIENT_SECRET | Set-Content src\Core\Secrets.h
build_script:
- qmake.exe build.pro -r -spec win32-msvc
- nmake
- cd qwt\
- jom -j1
- cd ..
- jom -j4
#notifications:
#- provider: GitHubPullRequest
# on_build_success: true
# on_build_failure: true
# on_build_status_changed: true
after_build:
- cd src\release
# copy dependencies
- windeployqt --release GoldenCheetah.exe
- copy c:\libs\10_Precompiled_DLL\usbexpress_3.5.1\USBXpress\USBXpress_API\Host\x64\SiUSBXp.dll
- copy c:\libs\10_Precompiled_DLL\libsamplerate64\lib\libsamplerate-0.dll
- copy c:\libs\10_Precompiled_DLL\VLC\win64\lib\libvlc*.dll
- xcopy /s /i /e /q c:\libs\10_Precompiled_DLL\VLC\win64\plugins plugins
- copy c:\OpenSSL-v111-Win64\bin\lib*.dll
- copy c:\OpenSSL-v111-Win64\license.txt "OpenSSL License.txt"
- xcopy /s /i /e /q C:\Python .
- copy C:\Python\LICENSE.txt "PYTHON LICENSE.txt"
- copy c:\tools\vcpkg\installed\x64-windows\bin\gsl*.dll
# ReadMe, license and icon files
- copy ..\Resources\win32\ReadMe.txt
- echo GoldenCheetah is licensed under the GNU General Public License v2 > license.txt
- echo. >> license.txt
- type ..\..\COPYING >> license.txt
- copy ..\Resources\win32\gc.ico
# Installer script
- copy ..\Resources\win32\GC3.6-Dev-Master-W64-QT5.14.2.nsi
# Build the installer
- makensis GC3.6-Dev-Master-W64-QT5.14.2.nsi
- move GoldenCheetah_v3.6-DEV_64bit_Windows.exe ..\..\GoldenCheetah_v3.6-DEV_x64.exe
- cd ..\..
- ps: Set-AppveyorBuildVariable -Name 'PUBLISH_BINARIES' -Value false
- ps: if ($env:APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED -Match "\[publish binaries\]") { Set-AppveyorBuildVariable -Name 'PUBLISH_BINARIES' -Value true }
test_script:
# minimum test
- src\release\GoldenCheetah --version 2>GCversionWindows.txt
- git log -1 >> GCversionWindows.txt
- ps: CertUtil -hashfile GoldenCheetah_v3.6-DEV_x64.exe sha256 | Select-Object -First 2 | Add-Content GCversionWindows.txt
- type GCversionWindows.txt
artifacts:
- path: GoldenCheetah_v3.6-DEV_x64.exe
name: GCinstaller
- path: GCversionWindows.txt
name: GCversionWindows
deploy:
# deploy continuous builds to s3
- provider: S3
access_key_id:
secure: RoEkfKfOnF7JHOiLZX5qfZM08X+bu4oaDzzSKgdooNM=
secret_access_key:
secure: GPAArawatirYwgpHJBthdrbvyFU5bBzPOdK7VYYPiG2YHYi/DNJZ5Q5qGK1A440p
bucket: goldencheetah-binaries
region: us-east-1
remove_files: true
set_public: true
folder: Windows
artifact: GCinstaller, GCversionWindows
on:
PUBLISH_BINARIES: true
APPVEYOR_REPO_NAME: "GoldenCheetah/GoldenCheetah"

View File

@@ -1,7 +1,4 @@
TEMPLATE = subdirs
SUBDIRS = qwt
unix:!macx {
SUBDIRS += kqoauth
}
SUBDIRS += src
CONFIG += ordered

View File

@@ -48,7 +48,7 @@ OverviewWindow::OverviewWindow(Context *context) :
{
setContentsMargins(0,0,0,0);
setProperty("color", GColor(COVERVIEWBACKGROUND));
setProperty("nomenu", true);
//setProperty("nomenu", true);
setShowTitle(false);
setControls(NULL);
@@ -57,6 +57,7 @@ OverviewWindow::OverviewWindow(Context *context) :
// add a view and scene and centre
scene = new QGraphicsScene(this);
view = new QGraphicsView(this);
view->viewport()->setAttribute(Qt::WA_AcceptTouchEvents, false); // stops it stealing focus on mouseover
scrollbar = new QScrollBar(Qt::Vertical, this);
// how to move etc
@@ -64,12 +65,6 @@ OverviewWindow::OverviewWindow(Context *context) :
view->setRenderHint(QPainter::Antialiasing, true);
view->setFrameStyle(QFrame::NoFrame);
view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
#ifdef Q_OS_LINUX
if (QGLFormat::openGLVersionFlags().testFlag(QGLFormat::OpenGL_Version_2_0)) {
view->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
}
#endif
view->setScene(scene);
// layout
@@ -182,12 +177,12 @@ OverviewWindow::setConfiguration(QString config)
newCard(tr("Notes"), 0, 4, 13, Card::META, "Notes");
// column 1
newCard(tr("HRV"), 1, 0, 9, Card::METRIC, "rMSSD");
newCard(tr("HRV rMSSD"), 1, 0, 9, Card::METRIC, "rMSSD");
newCard(tr("Heartrate"), 1, 1, 5, Card::METRIC, "average_hr");
newCard(tr("Heartrate Zones"), 1, 2, 11, Card::ZONE, RideFile::hr);
newCard(tr("Climbing"), 1, 3, 5, Card::METRIC, "elevation_gain");
newCard(tr("Cadence"), 1, 4, 5, Card::METRIC, "average_cad");
newCard(tr("Equivalent Power"), 1, 5, 5, Card::METRIC, "coggan_np");
newCard(tr("Work"), 1, 6, 5, Card::METRIC, "total_work");
// column 2
newCard(tr("RPE"), 2, 0, 9, Card::RPE);
@@ -199,7 +194,9 @@ OverviewWindow::setConfiguration(QString config)
newCard(tr("Intensity"), 3, 0, 9, Card::METRIC, "coggan_if");
newCard(tr("Power"), 3, 1, 5, Card::METRIC, "average_power");
newCard(tr("Power Zones"), 3, 2, 11, Card::ZONE, RideFile::watts);
newCard(tr("Power Model"), 3, 3, 17);
newCard(tr("Equivalent Power"), 3, 3, 5, Card::METRIC, "coggan_np");
newCard(tr("Peak Power Index"), 3, 4, 5, Card::METRIC, "peak_power_index");
newCard(tr("Variability"), 3, 5, 5, Card::METRIC, "coggam_variability_index");
// column 4
newCard(tr("Distance"), 4, 0, 9, Card::METRIC, "total_distance");
@@ -557,6 +554,8 @@ static const QStringList timeInZonesWBAL = QStringList()
void
Card::setData(RideItem *item)
{
if (item == NULL || item->ride() == NULL) return;
// use ride colors in painting?
ridecolor = item->color;
@@ -2746,7 +2745,7 @@ OverviewWindow::eventFilter(QObject *, QEvent *event)
// min max width
if (setcolumn < 800) setcolumn = 800;
if (setcolumn > 2400) setcolumn = 2400;
if (setcolumn > 4400) setcolumn = 4400;
columns[stateData.xresize.column] = setcolumn;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 556 KiB

BIN
doc/wiki/WebChartConfig.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

BIN
doc/wiki/dataseries.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

BIN
doc/wiki/worktime.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

75
levmar/Axb.c Normal file
View File

@@ -0,0 +1,75 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Solution of linear systems involved in the Levenberg - Marquardt
// minimization algorithm
// Copyright (C) 2004 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/********************************************************************************
* LAPACK-based implementations for various linear system solvers. The same core
* code is used with appropriate #defines to derive single and double precision
* solver versions, see also Axb_core.c
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "levmar.h"
#include "misc.h"
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_CNST(x) (x)
#ifndef HAVE_LAPACK
#include <float.h>
#define LM_REAL_EPSILON DBL_EPSILON
#endif
#include "Axb_core.c"
#undef LM_REAL
#undef LM_PREFIX
#undef LM_CNST
#undef LM_REAL_EPSILON
#endif /* LM_DBL_PREC */
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#ifndef HAVE_LAPACK
#define LM_REAL_EPSILON FLT_EPSILON
#endif
#include "Axb_core.c"
#undef LM_REAL
#undef LM_PREFIX
#undef __SUBCNST
#undef LM_CNST
#undef LM_REAL_EPSILON
#endif /* LM_SNGL_PREC */

1282
levmar/Axb_core.c Normal file

File diff suppressed because it is too large Load Diff

49
levmar/compiler.h Normal file
View File

@@ -0,0 +1,49 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef _COMPILER_H_
#define _COMPILER_H_
/* note: intel's icc defines both __ICC & __INTEL_COMPILER.
* Also, some compilers other than gcc define __GNUC__,
* therefore gcc should be checked last
*/
#ifdef _MSC_VER
#define inline __inline // MSVC
#elif !defined(__ICC) && !defined(__INTEL_COMPILER) && !defined(__GNUC__)
#define inline // other than MSVC, ICC, GCC: define empty
#endif
#ifdef _MSC_VER
#define LM_FINITE _finite // MSVC
#elif defined(__ICC) || defined(__INTEL_COMPILER) || defined(__GNUC__)
#define LM_FINITE finite // ICC, GCC
#else
#define LM_FINITE finite // other than MSVC, ICC, GCC, let's hope this will work
#endif
#ifdef _MSC_VER
#define LM_ISINF(x) (!_finite(x) && !_isnan(x)) // MSVC
#elif defined(__ICC) || defined(__INTEL_COMPILER) || defined(__GNUC__)
#define LM_ISINF(x) isinf(x) // ICC, GCC
#else
#define LM_ISINF(x) isinf(x) // other than MSVC, ICC, GCC, let's hope this will work
#endif
#endif /* _COMPILER_H_ */

398
levmar/levmar.h Normal file
View File

@@ -0,0 +1,398 @@
/*
////////////////////////////////////////////////////////////////////////////////////
//
// Prototypes and definitions for the Levenberg - Marquardt minimization algorithm
// Copyright (C) 2004 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
////////////////////////////////////////////////////////////////////////////////////
*/
#ifndef _LEVMAR_H_
#define _LEVMAR_H_
/************************************* Start of configuration options *************************************/
/* Note that when compiling with CMake, this configuration section is automatically generated
* based on the user's input, see levmar.h.in
*/
/* specifies whether to use LAPACK or not. Using LAPACK is strongly recommended */
//#define HAVE_LAPACK
/* specifies whether the PLASMA parallel library for multicore CPUs is available */
/* #undef HAVE_PLASMA */
/* to avoid the overhead of repeated mallocs(), routines in Axb.c can be instructed to
* retain working memory between calls. Such a choice, however, renders these routines
* non-reentrant and is not safe in a shared memory multiprocessing environment.
* Bellow, an attempt is made to issue a warning if this option is turned on and OpenMP
* is being used (note that this will work only if omp.h is included before levmar.h)
*/
#define LINSOLVERS_RETAIN_MEMORY
#if (defined(_OPENMP))
# ifdef LINSOLVERS_RETAIN_MEMORY
# ifdef _MSC_VER
# pragma message("LINSOLVERS_RETAIN_MEMORY is not safe in a multithreaded environment and should be turned off!")
# else
# warning LINSOLVERS_RETAIN_MEMORY is not safe in a multithreaded environment and should be turned off!
# endif /* _MSC_VER */
# endif /* LINSOLVERS_RETAIN_MEMORY */
#endif /* _OPENMP */
/* specifies whether double precision routines will be compiled or not */
#define LM_DBL_PREC
/* specifies whether single precision routines will be compiled or not */
#define LM_SNGL_PREC
/****************** End of configuration options, no changes necessary beyond this point ******************/
#ifdef __cplusplus
extern "C" {
#endif
/* work arrays size for ?levmar_der and ?levmar_dif functions.
* should be multiplied by sizeof(double) or sizeof(float) to be converted to bytes
*/
#define LM_DER_WORKSZ(npar, nmeas) (2*(nmeas) + 4*(npar) + (nmeas)*(npar) + (npar)*(npar))
#define LM_DIF_WORKSZ(npar, nmeas) (4*(nmeas) + 4*(npar) + (nmeas)*(npar) + (npar)*(npar))
/* work arrays size for ?levmar_bc_der and ?levmar_bc_dif functions.
* should be multiplied by sizeof(double) or sizeof(float) to be converted to bytes
*/
#define LM_BC_DER_WORKSZ(npar, nmeas) (2*(nmeas) + 4*(npar) + (nmeas)*(npar) + (npar)*(npar))
#define LM_BC_DIF_WORKSZ(npar, nmeas) LM_BC_DER_WORKSZ((npar), (nmeas)) /* LEVMAR_BC_DIF currently implemented using LEVMAR_BC_DER()! */
/* work arrays size for ?levmar_lec_der and ?levmar_lec_dif functions.
* should be multiplied by sizeof(double) or sizeof(float) to be converted to bytes
*/
#define LM_LEC_DER_WORKSZ(npar, nmeas, nconstr) LM_DER_WORKSZ((npar)-(nconstr), (nmeas))
#define LM_LEC_DIF_WORKSZ(npar, nmeas, nconstr) LM_DIF_WORKSZ((npar)-(nconstr), (nmeas))
/* work arrays size for ?levmar_blec_der and ?levmar_blec_dif functions.
* should be multiplied by sizeof(double) or sizeof(float) to be converted to bytes
*/
#define LM_BLEC_DER_WORKSZ(npar, nmeas, nconstr) LM_LEC_DER_WORKSZ((npar), (nmeas)+(npar), (nconstr))
#define LM_BLEC_DIF_WORKSZ(npar, nmeas, nconstr) LM_LEC_DIF_WORKSZ((npar), (nmeas)+(npar), (nconstr))
/* work arrays size for ?levmar_bleic_der and ?levmar_bleic_dif functions.
* should be multiplied by sizeof(double) or sizeof(float) to be converted to bytes
*/
#define LM_BLEIC_DER_WORKSZ(npar, nmeas, nconstr1, nconstr2) LM_BLEC_DER_WORKSZ((npar)+(nconstr2), (nmeas)+(nconstr2), (nconstr1)+(nconstr2))
#define LM_BLEIC_DIF_WORKSZ(npar, nmeas, nconstr1, nconstr2) LM_BLEC_DIF_WORKSZ((npar)+(nconstr2), (nmeas)+(nconstr2), (nconstr1)+(nconstr2))
#define LM_OPTS_SZ 5 /* max(4, 5) */
#define LM_INFO_SZ 10
#define LM_ERROR -1
#define LM_INIT_MU 1E-03
#define LM_STOP_THRESH 1E-17
#define LM_DIFF_DELTA 1E-06
#define LM_VERSION "2.6 (November 2011)"
#ifdef LM_DBL_PREC
/* double precision LM, with & without Jacobian */
/* unconstrained minimization */
extern int dlevmar_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, int itmax, double *opts,
double *info, double *work, double *covar, void *adata);
extern int dlevmar_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, int itmax, double *opts,
double *info, double *work, double *covar, void *adata);
/* box-constrained minimization */
extern int dlevmar_bc_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub, double *dscl,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
extern int dlevmar_bc_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub, double *dscl,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
#ifdef HAVE_LAPACK
/* linear equation constrained minimization */
extern int dlevmar_lec_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *A, double *b, int k,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
extern int dlevmar_lec_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *A, double *b, int k,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
/* box & linear equation constrained minimization */
extern int dlevmar_blec_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub, double *A, double *b, int k, double *wghts,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
extern int dlevmar_blec_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub, double *A, double *b, int k, double *wghts,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
/* box, linear equations & inequalities constrained minimization */
extern int dlevmar_bleic_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub,
double *A, double *b, int k1, double *C, double *d, int k2,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
extern int dlevmar_bleic_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub,
double *A, double *b, int k1, double *C, double *d, int k2,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
/* box & linear inequality constraints */
extern int dlevmar_blic_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub, double *C, double *d, int k2,
int itmax, double opts[4], double info[LM_INFO_SZ], double *work, double *covar, void *adata);
extern int dlevmar_blic_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub, double *C, double *d, int k2,
int itmax, double opts[5], double info[LM_INFO_SZ], double *work, double *covar, void *adata);
/* linear equation & inequality constraints */
extern int dlevmar_leic_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *A, double *b, int k1, double *C, double *d, int k2,
int itmax, double opts[4], double info[LM_INFO_SZ], double *work, double *covar, void *adata);
extern int dlevmar_leic_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *A, double *b, int k1, double *C, double *d, int k2,
int itmax, double opts[5], double info[LM_INFO_SZ], double *work, double *covar, void *adata);
/* linear inequality constraints */
extern int dlevmar_lic_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *C, double *d, int k2,
int itmax, double opts[4], double info[LM_INFO_SZ], double *work, double *covar, void *adata);
extern int dlevmar_lic_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *C, double *d, int k2,
int itmax, double opts[5], double info[LM_INFO_SZ], double *work, double *covar, void *adata);
#endif /* HAVE_LAPACK */
#endif /* LM_DBL_PREC */
#ifdef LM_SNGL_PREC
/* single precision LM, with & without Jacobian */
/* unconstrained minimization */
extern int slevmar_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, int itmax, float *opts,
float *info, float *work, float *covar, void *adata);
extern int slevmar_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, int itmax, float *opts,
float *info, float *work, float *covar, void *adata);
/* box-constrained minimization */
extern int slevmar_bc_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub, float *dscl,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
extern int slevmar_bc_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub, float *dscl,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
#ifdef HAVE_LAPACK
/* linear equation constrained minimization */
extern int slevmar_lec_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *A, float *b, int k,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
extern int slevmar_lec_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *A, float *b, int k,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
/* box & linear equation constrained minimization */
extern int slevmar_blec_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub, float *A, float *b, int k, float *wghts,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
extern int slevmar_blec_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub, float *A, float *b, int k, float *wghts,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
/* box, linear equations & inequalities constrained minimization */
extern int slevmar_bleic_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub,
float *A, float *b, int k1, float *C, float *d, int k2,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
extern int slevmar_bleic_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub,
float *A, float *b, int k1, float *C, float *d, int k2,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
/* box & linear inequality constraints */
extern int slevmar_blic_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub, float *C, float *d, int k2,
int itmax, float opts[4], float info[LM_INFO_SZ], float *work, float *covar, void *adata);
extern int slevmar_blic_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub, float *C, float *d, int k2,
int itmax, float opts[5], float info[LM_INFO_SZ], float *work, float *covar, void *adata);
/* linear equality & inequality constraints */
extern int slevmar_leic_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *A, float *b, int k1, float *C, float *d, int k2,
int itmax, float opts[4], float info[LM_INFO_SZ], float *work, float *covar, void *adata);
extern int slevmar_leic_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *A, float *b, int k1, float *C, float *d, int k2,
int itmax, float opts[5], float info[LM_INFO_SZ], float *work, float *covar, void *adata);
/* linear inequality constraints */
extern int slevmar_lic_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *C, float *d, int k2,
int itmax, float opts[4], float info[LM_INFO_SZ], float *work, float *covar, void *adata);
extern int slevmar_lic_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *C, float *d, int k2,
int itmax, float opts[5], float info[LM_INFO_SZ], float *work, float *covar, void *adata);
#endif /* HAVE_LAPACK */
#endif /* LM_SNGL_PREC */
/* linear system solvers */
#ifdef HAVE_LAPACK
#ifdef LM_DBL_PREC
extern int dAx_eq_b_QR(double *A, double *B, double *x, int m);
extern int dAx_eq_b_QRLS(double *A, double *B, double *x, int m, int n);
extern int dAx_eq_b_Chol(double *A, double *B, double *x, int m);
extern int dAx_eq_b_LU(double *A, double *B, double *x, int m);
extern int dAx_eq_b_SVD(double *A, double *B, double *x, int m);
extern int dAx_eq_b_BK(double *A, double *B, double *x, int m);
#endif /* LM_DBL_PREC */
#ifdef LM_SNGL_PREC
extern int sAx_eq_b_QR(float *A, float *B, float *x, int m);
extern int sAx_eq_b_QRLS(float *A, float *B, float *x, int m, int n);
extern int sAx_eq_b_Chol(float *A, float *B, float *x, int m);
extern int sAx_eq_b_LU(float *A, float *B, float *x, int m);
extern int sAx_eq_b_SVD(float *A, float *B, float *x, int m);
extern int sAx_eq_b_BK(float *A, float *B, float *x, int m);
#endif /* LM_SNGL_PREC */
#else /* no LAPACK */
#ifdef LM_DBL_PREC
extern int dAx_eq_b_LU_noLapack(double *A, double *B, double *x, int n);
#endif /* LM_DBL_PREC */
#ifdef LM_SNGL_PREC
extern int sAx_eq_b_LU_noLapack(float *A, float *B, float *x, int n);
#endif /* LM_SNGL_PREC */
#endif /* HAVE_LAPACK */
#ifdef HAVE_PLASMA
#ifdef LM_DBL_PREC
extern int dAx_eq_b_PLASMA_Chol(double *A, double *B, double *x, int m);
#endif
#ifdef LM_SNGL_PREC
extern int sAx_eq_b_PLASMA_Chol(float *A, float *B, float *x, int m);
#endif
extern void levmar_PLASMA_setnbcores(int cores);
#endif /* HAVE_PLASMA */
/* Jacobian verification, double & single precision */
#ifdef LM_DBL_PREC
extern void dlevmar_chkjac(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, int m, int n, void *adata, double *err);
#endif /* LM_DBL_PREC */
#ifdef LM_SNGL_PREC
extern void slevmar_chkjac(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, int m, int n, void *adata, float *err);
#endif /* LM_SNGL_PREC */
/* miscellaneous: standard deviation, coefficient of determination (R2),
* Pearson's correlation coefficient for best-fit parameters
*/
#ifdef LM_DBL_PREC
extern double dlevmar_stddev( double *covar, int m, int i);
extern double dlevmar_corcoef(double *covar, int m, int i, int j);
extern double dlevmar_R2(void (*func)(double *p, double *hx, int m, int n, void *adata), double *p, double *x, int m, int n, void *adata);
#endif /* LM_DBL_PREC */
#ifdef LM_SNGL_PREC
extern float slevmar_stddev( float *covar, int m, int i);
extern float slevmar_corcoef(float *covar, int m, int i, int j);
extern float slevmar_R2(void (*func)(float *p, float *hx, int m, int n, void *adata), float *p, float *x, int m, int n, void *adata);
extern void slevmar_locscale(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, void *adata,
int howto, float locscl[2], float **residptr);
extern int slevmar_outlid(float *r, int n, float thresh, float ls[2], char *outlmap);
#endif /* LM_SNGL_PREC */
#ifdef __cplusplus
}
#endif
#endif /* _LEVMAR_H_ */

83
levmar/lm.c Normal file
View File

@@ -0,0 +1,83 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/********************************************************************************
* Levenberg-Marquardt nonlinear minimization. The same core code is used with
* appropriate #defines to derive single and double precision versions, see
* also lm_core.c
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "levmar.h"
#include "compiler.h"
#include "misc.h"
#define EPSILON 1E-12
#define ONE_THIRD 0.3333333334 /* 1.0/3.0 */
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define LM_REAL_MAX FLT_MAX
#define LM_REAL_MIN -FLT_MAX
#define LM_REAL_EPSILON FLT_EPSILON
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#include "lm_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_EPSILON
#undef LM_REAL_MIN
#undef __SUBCNST
#undef LM_CNST
#endif /* LM_SNGL_PREC */
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_REAL_MAX DBL_MAX
#define LM_REAL_MIN -DBL_MAX
#define LM_REAL_EPSILON DBL_EPSILON
#define LM_CNST(x) (x)
#include "lm_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_EPSILON
#undef LM_REAL_MIN
#undef LM_CNST
#endif /* LM_DBL_PREC */

11
levmar/lm.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef _DEPR_LM_H_
#define _DEPR_LM_H_
#ifdef _MSC_VER
#pragma message("lm.h is deprecated, please use levmar.h instead!")
#else
#error lm.h is deprecated, please use levmar.h instead!
#endif /* _MSC_VER */
#endif /* _DEPR_LM_H_ */

858
levmar/lm_core.c Normal file
View File

@@ -0,0 +1,858 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef LM_REAL // not included by lm.c
#error This file should not be compiled directly!
#endif
/* precision-specific definitions */
#define LEVMAR_DER LM_ADD_PREFIX(levmar_der)
#define LEVMAR_DIF LM_ADD_PREFIX(levmar_dif)
#define LEVMAR_FDIF_FORW_JAC_APPROX LM_ADD_PREFIX(levmar_fdif_forw_jac_approx)
#define LEVMAR_FDIF_CENT_JAC_APPROX LM_ADD_PREFIX(levmar_fdif_cent_jac_approx)
#define LEVMAR_TRANS_MAT_MAT_MULT LM_ADD_PREFIX(levmar_trans_mat_mat_mult)
#define LEVMAR_L2NRMXMY LM_ADD_PREFIX(levmar_L2nrmxmy)
#define LEVMAR_COVAR LM_ADD_PREFIX(levmar_covar)
#ifdef HAVE_LAPACK
#define AX_EQ_B_LU LM_ADD_PREFIX(Ax_eq_b_LU)
#define AX_EQ_B_CHOL LM_ADD_PREFIX(Ax_eq_b_Chol)
#define AX_EQ_B_QR LM_ADD_PREFIX(Ax_eq_b_QR)
#define AX_EQ_B_QRLS LM_ADD_PREFIX(Ax_eq_b_QRLS)
#define AX_EQ_B_SVD LM_ADD_PREFIX(Ax_eq_b_SVD)
#define AX_EQ_B_BK LM_ADD_PREFIX(Ax_eq_b_BK)
#else
#define AX_EQ_B_LU LM_ADD_PREFIX(Ax_eq_b_LU_noLapack)
#endif /* HAVE_LAPACK */
#ifdef HAVE_PLASMA
#define AX_EQ_B_PLASMA_CHOL LM_ADD_PREFIX(Ax_eq_b_PLASMA_Chol)
#endif
/*
* This function seeks the parameter vector p that best describes the measurements vector x.
* More precisely, given a vector function func : R^m --> R^n with n>=m,
* it finds p s.t. func(p) ~= x, i.e. the squared second order (i.e. L2) norm of
* e=x-func(p) is minimized.
*
* This function requires an analytic Jacobian. In case the latter is unavailable,
* use LEVMAR_DIF() bellow
*
* Returns the number of iterations (>=0) if successful, LM_ERROR if failed
*
* For more details, see K. Madsen, H.B. Nielsen and O. Tingleff's lecture notes on
* non-linear least squares at http://www.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf
*/
int LEVMAR_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata), /* function to evaluate the Jacobian \part x / \part p */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[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_REAL info[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_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
*/
{
register int i, j, k, l;
int worksz, freework=0, issolved;
/* temp work arrays */
LM_REAL *e, /* nx1 */
*hx, /* \hat{x}_i, nx1 */
*jacTe, /* J^T e_i mx1 */
*jac, /* nxm */
*jacTjac, /* mxm */
*Dp, /* mx1 */
*diag_jacTjac, /* diagonal of J^T J, mx1 */
*pDp; /* p + Dp, mx1 */
register LM_REAL mu, /* damping constant */
tmp; /* mainly used in matrix & vector multiplications */
LM_REAL p_eL2, jacTe_inf, pDp_eL2; /* ||e(p)||_2, ||J^T e||_inf, ||e(p+Dp)||_2 */
LM_REAL p_L2, Dp_L2=LM_REAL_MAX, dF, dL;
LM_REAL tau, eps1, eps2, eps2_sq, eps3;
LM_REAL init_p_eL2;
int nu=2, nu2, stop=0, nfev, njev=0, nlss=0;
const int nm=n*m;
int (*linsolver)(LM_REAL *A, LM_REAL *B, LM_REAL *x, int m)=NULL;
mu=jacTe_inf=0.0; /* -Wall */
if(n<m){
fprintf(stderr, LCAT(LEVMAR_DER, "(): cannot solve a problem with fewer measurements [%d] than unknowns [%d]\n"), n, m);
return LM_ERROR;
}
if(!jacf){
fprintf(stderr, RCAT("No function specified for computing the Jacobian in ", LEVMAR_DER)
RCAT("().\nIf no such function is available, use ", LEVMAR_DIF) RCAT("() rather than ", LEVMAR_DER) "()\n");
return LM_ERROR;
}
if(opts){
tau=opts[0];
eps1=opts[1];
eps2=opts[2];
eps2_sq=opts[2]*opts[2];
eps3=opts[3];
}
else{ // use default values
tau=LM_CNST(LM_INIT_MU);
eps1=LM_CNST(LM_STOP_THRESH);
eps2=LM_CNST(LM_STOP_THRESH);
eps2_sq=LM_CNST(LM_STOP_THRESH)*LM_CNST(LM_STOP_THRESH);
eps3=LM_CNST(LM_STOP_THRESH);
}
if(!work){
worksz=LM_DER_WORKSZ(m, n); //2*n+4*m + n*m + m*m;
work=(LM_REAL *)malloc(worksz*sizeof(LM_REAL)); /* allocate a big chunk in one step */
if(!work){
fprintf(stderr, LCAT(LEVMAR_DER, "(): memory allocation request failed\n"));
return LM_ERROR;
}
freework=1;
}
/* set up work arrays */
e=work;
hx=e + n;
jacTe=hx + n;
jac=jacTe + m;
jacTjac=jac + nm;
Dp=jacTjac + m*m;
diag_jacTjac=Dp + m;
pDp=diag_jacTjac + m;
/* compute e=x - f(p) and its L2 norm */
(*func)(p, hx, m, n, adata); nfev=1;
/* ### e=x-hx, p_eL2=||e|| */
#if 1
p_eL2=LEVMAR_L2NRMXMY(e, x, hx, n);
#else
for(i=0, p_eL2=0.0; i<n; ++i){
e[i]=tmp=x[i]-hx[i];
p_eL2+=tmp*tmp;
}
#endif
init_p_eL2=p_eL2;
if(!LM_FINITE(p_eL2)) stop=7;
for(k=0; k<itmax && !stop; ++k){
/* Note that p and e have been updated at a previous iteration */
if(p_eL2<=eps3){ /* error is small */
stop=6;
break;
}
/* Compute the Jacobian J at p, J^T J, J^T e, ||J^T e||_inf and ||p||^2.
* Since J^T J is symmetric, its computation can be sped up by computing
* only its upper triangular part and copying it to the lower part
*/
(*jacf)(p, jac, m, n, adata); ++njev;
/* J^T J, J^T e */
if(nm<__BLOCKSZ__SQ){ // this is a small problem
/* J^T*J_ij = \sum_l J^T_il * J_lj = \sum_l J_li * J_lj.
* Thus, the product J^T J can be computed using an outer loop for
* l that adds J_li*J_lj to each element ij of the result. Note that
* with this scheme, the accesses to J and JtJ are always along rows,
* therefore induces less cache misses compared to the straightforward
* algorithm for computing the product (i.e., l loop is innermost one).
* A similar scheme applies to the computation of J^T e.
* However, for large minimization problems (i.e., involving a large number
* of unknowns and measurements) for which J/J^T J rows are too large to
* fit in the L1 cache, even this scheme incures many cache misses. In
* such cases, a cache-efficient blocking scheme is preferable.
*
* Thanks to John Nitao of Lawrence Livermore Lab for pointing out this
* performance problem.
*
* Note that the non-blocking algorithm is faster on small
* problems since in this case it avoids the overheads of blocking.
*/
/* looping downwards saves a few computations */
register int l;
register LM_REAL alpha, *jaclm, *jacTjacim;
for(i=m*m; i-->0; )
jacTjac[i]=0.0;
for(i=m; i-->0; )
jacTe[i]=0.0;
for(l=n; l-->0; ){
jaclm=jac+l*m;
for(i=m; i-->0; ){
jacTjacim=jacTjac+i*m;
alpha=jaclm[i]; //jac[l*m+i];
for(j=i+1; j-->0; ) /* j<=i computes lower triangular part only */
jacTjacim[j]+=jaclm[j]*alpha; //jacTjac[i*m+j]+=jac[l*m+j]*alpha
/* J^T e */
jacTe[i]+=alpha*e[l];
}
}
for(i=m; i-->0; ) /* copy to upper part */
for(j=i+1; j<m; ++j)
jacTjac[i*m+j]=jacTjac[j*m+i];
}
else{ // this is a large problem
/* Cache efficient computation of J^T J based on blocking
*/
LEVMAR_TRANS_MAT_MAT_MULT(jac, jacTjac, n, m);
/* cache efficient computation of J^T e */
for(i=0; i<m; ++i)
jacTe[i]=0.0;
for(i=0; i<n; ++i){
register LM_REAL *jacrow;
for(l=0, jacrow=jac+i*m, tmp=e[i]; l<m; ++l)
jacTe[l]+=jacrow[l]*tmp;
}
}
/* Compute ||J^T e||_inf and ||p||^2 */
for(i=0, p_L2=jacTe_inf=0.0; i<m; ++i){
if(jacTe_inf < (tmp=FABS(jacTe[i]))) jacTe_inf=tmp;
diag_jacTjac[i]=jacTjac[i*m+i]; /* save diagonal entries so that augmentation can be later canceled */
p_L2+=p[i]*p[i];
}
//p_L2=sqrt(p_L2);
#if 0
if(!(k%100)){
printf("Current estimate: ");
for(i=0; i<m; ++i)
printf("%.9g ", p[i]);
printf("-- errors %.9g %0.9g\n", jacTe_inf, p_eL2);
}
#endif
/* check for convergence */
if((jacTe_inf <= eps1)){
Dp_L2=0.0; /* no increment for p in this case */
stop=1;
break;
}
/* compute initial damping factor */
if(k==0){
for(i=0, tmp=LM_REAL_MIN; i<m; ++i)
if(diag_jacTjac[i]>tmp) tmp=diag_jacTjac[i]; /* find max diagonal element */
mu=tau*tmp;
}
/* determine increment using adaptive damping */
while(1){
/* augment normal equations */
for(i=0; i<m; ++i)
jacTjac[i*m+i]+=mu;
/* solve augmented equations */
#ifdef HAVE_LAPACK
/* 7 alternatives are available: LU, Cholesky + Cholesky with PLASMA, LDLt, 2 variants of QR decomposition and SVD.
* For matrices with dimensions of at least a few hundreds, the PLASMA implementation of Cholesky is the fastest.
* From the serial solvers, Cholesky is the fastest but might occasionally be inapplicable due to numerical round-off;
* QR is slower but more robust; SVD is the slowest but most robust; LU is quite robust but
* slower than LDLt; LDLt offers a good tradeoff between robustness and speed
*/
issolved=AX_EQ_B_BK(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_BK;
//issolved=AX_EQ_B_LU(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_LU;
//issolved=AX_EQ_B_CHOL(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_CHOL;
#ifdef HAVE_PLASMA
//issolved=AX_EQ_B_PLASMA_CHOL(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_PLASMA_CHOL;
#endif
//issolved=AX_EQ_B_QR(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_QR;
//issolved=AX_EQ_B_QRLS(jacTjac, jacTe, Dp, m, m); ++nlss; linsolver=(int (*)(LM_REAL *A, LM_REAL *B, LM_REAL *x, int m))AX_EQ_B_QRLS;
//issolved=AX_EQ_B_SVD(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_SVD;
#else
/* use the LU included with levmar */
issolved=AX_EQ_B_LU(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_LU;
#endif /* HAVE_LAPACK */
if(issolved){
/* compute p's new estimate and ||Dp||^2 */
for(i=0, Dp_L2=0.0; i<m; ++i){
pDp[i]=p[i] + (tmp=Dp[i]);
Dp_L2+=tmp*tmp;
}
//Dp_L2=sqrt(Dp_L2);
if(Dp_L2<=eps2_sq*p_L2){ /* relative change in p is small, stop */
//if(Dp_L2<=eps2*(p_L2 + eps2)){ /* relative change in p is small, stop */
stop=2;
break;
}
if(Dp_L2>=(p_L2+eps2)/(LM_CNST(EPSILON)*LM_CNST(EPSILON))){ /* almost singular */
//if(Dp_L2>=(p_L2+eps2)/LM_CNST(EPSILON)){ /* almost singular */
stop=4;
break;
}
(*func)(pDp, hx, m, n, adata); ++nfev; /* evaluate function at p + Dp */
/* compute ||e(pDp)||_2 */
/* ### hx=x-hx, pDp_eL2=||hx|| */
#if 1
pDp_eL2=LEVMAR_L2NRMXMY(hx, x, hx, n);
#else
for(i=0, pDp_eL2=0.0; i<n; ++i){
hx[i]=tmp=x[i]-hx[i];
pDp_eL2+=tmp*tmp;
}
#endif
if(!LM_FINITE(pDp_eL2)){ /* sum of squares is not finite, most probably due to a user error.
* This check makes sure that the inner loop does not run indefinitely.
* Thanks to Steve Danauskas for reporting such cases
*/
stop=7;
break;
}
for(i=0, dL=0.0; i<m; ++i)
dL+=Dp[i]*(mu*Dp[i]+jacTe[i]);
dF=p_eL2-pDp_eL2;
if(dL>0.0 && dF>0.0){ /* reduction in error, increment is accepted */
tmp=(LM_CNST(2.0)*dF/dL-LM_CNST(1.0));
tmp=LM_CNST(1.0)-tmp*tmp*tmp;
mu=mu*( (tmp>=LM_CNST(ONE_THIRD))? tmp : LM_CNST(ONE_THIRD) );
nu=2;
for(i=0 ; i<m; ++i) /* update p's estimate */
p[i]=pDp[i];
for(i=0; i<n; ++i) /* update e and ||e||_2 */
e[i]=hx[i];
p_eL2=pDp_eL2;
break;
}
}
/* if this point is reached, either the linear system could not be solved or
* the error did not reduce; in any case, the increment must be rejected
*/
mu*=nu;
nu2=nu<<1; // 2*nu;
if(nu2<=nu){ /* nu has wrapped around (overflown). Thanks to Frank Jordan for spotting this case */
stop=5;
break;
}
nu=nu2;
for(i=0; i<m; ++i) /* restore diagonal J^T J entries */
jacTjac[i*m+i]=diag_jacTjac[i];
} /* inner loop */
}
if(k>=itmax) stop=3;
for(i=0; i<m; ++i) /* restore diagonal J^T J entries */
jacTjac[i*m+i]=diag_jacTjac[i];
if(info){
info[0]=init_p_eL2;
info[1]=p_eL2;
info[2]=jacTe_inf;
info[3]=Dp_L2;
for(i=0, tmp=LM_REAL_MIN; i<m; ++i)
if(tmp<jacTjac[i*m+i]) tmp=jacTjac[i*m+i];
info[4]=mu/tmp;
info[5]=(LM_REAL)k;
info[6]=(LM_REAL)stop;
info[7]=(LM_REAL)nfev;
info[8]=(LM_REAL)njev;
info[9]=(LM_REAL)nlss;
}
/* covariance matrix */
if(covar){
LEVMAR_COVAR(jacTjac, covar, p_eL2, m, n);
}
if(freework) free(work);
#ifdef LINSOLVERS_RETAIN_MEMORY
if(linsolver) (*linsolver)(NULL, NULL, NULL, 0);
#endif
return (stop!=4 && stop!=7)? k : LM_ERROR;
}
/* Secant version of the LEVMAR_DER() function above: the Jacobian is approximated with
* the aid of finite differences (forward or central, see the comment for the opts argument)
*/
int LEVMAR_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[5], /* I: opts[0-4] = minim. options [\mu, \epsilon1, \epsilon2, \epsilon3, \delta]. Respectively the
* 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_REAL info[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_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
*/
{
register int i, j, k, l;
int worksz, freework=0, issolved;
/* temp work arrays */
LM_REAL *e, /* nx1 */
*hx, /* \hat{x}_i, nx1 */
*jacTe, /* J^T e_i mx1 */
*jac, /* nxm */
*jacTjac, /* mxm */
*Dp, /* mx1 */
*diag_jacTjac, /* diagonal of J^T J, mx1 */
*pDp, /* p + Dp, mx1 */
*wrk, /* nx1 */
*wrk2; /* nx1, used only for holding a temporary e vector and when differentiating with central differences */
int using_ffdif=1;
register LM_REAL mu, /* damping constant */
tmp; /* mainly used in matrix & vector multiplications */
LM_REAL p_eL2, jacTe_inf, pDp_eL2; /* ||e(p)||_2, ||J^T e||_inf, ||e(p+Dp)||_2 */
LM_REAL p_L2, Dp_L2=LM_REAL_MAX, dF, dL;
LM_REAL tau, eps1, eps2, eps2_sq, eps3, delta;
LM_REAL init_p_eL2;
int nu, nu2, stop=0, nfev, njap=0, nlss=0, K=(m>=10)? m: 10, updjac, updp=1, newjac;
const int nm=n*m;
int (*linsolver)(LM_REAL *A, LM_REAL *B, LM_REAL *x, int m)=NULL;
mu=jacTe_inf=p_L2=0.0; /* -Wall */
updjac=newjac=0; /* -Wall */
if(n<m){
fprintf(stderr, LCAT(LEVMAR_DIF, "(): cannot solve a problem with fewer measurements [%d] than unknowns [%d]\n"), n, m);
return LM_ERROR;
}
if(opts){
tau=opts[0];
eps1=opts[1];
eps2=opts[2];
eps2_sq=opts[2]*opts[2];
eps3=opts[3];
delta=opts[4];
if(delta<0.0){
delta=-delta; /* make positive */
using_ffdif=0; /* use central differencing */
}
}
else{ // use default values
tau=LM_CNST(LM_INIT_MU);
eps1=LM_CNST(LM_STOP_THRESH);
eps2=LM_CNST(LM_STOP_THRESH);
eps2_sq=LM_CNST(LM_STOP_THRESH)*LM_CNST(LM_STOP_THRESH);
eps3=LM_CNST(LM_STOP_THRESH);
delta=LM_CNST(LM_DIFF_DELTA);
}
if(!work){
worksz=LM_DIF_WORKSZ(m, n); //4*n+4*m + n*m + m*m;
work=(LM_REAL *)malloc(worksz*sizeof(LM_REAL)); /* allocate a big chunk in one step */
if(!work){
fprintf(stderr, LCAT(LEVMAR_DIF, "(): memory allocation request failed\n"));
return LM_ERROR;
}
freework=1;
}
/* set up work arrays */
e=work;
hx=e + n;
jacTe=hx + n;
jac=jacTe + m;
jacTjac=jac + nm;
Dp=jacTjac + m*m;
diag_jacTjac=Dp + m;
pDp=diag_jacTjac + m;
wrk=pDp + m;
wrk2=wrk + n;
/* compute e=x - f(p) and its L2 norm */
(*func)(p, hx, m, n, adata); nfev=1;
/* ### e=x-hx, p_eL2=||e|| */
#if 1
p_eL2=LEVMAR_L2NRMXMY(e, x, hx, n);
#else
for(i=0, p_eL2=0.0; i<n; ++i){
e[i]=tmp=x[i]-hx[i];
p_eL2+=tmp*tmp;
}
#endif
init_p_eL2=p_eL2;
if(!LM_FINITE(p_eL2)) stop=7;
nu=20; /* force computation of J */
for(k=0; k<itmax && !stop; ++k){
/* Note that p and e have been updated at a previous iteration */
if(p_eL2<=eps3){ /* error is small */
stop=6;
break;
}
/* Compute the Jacobian J at p, J^T J, J^T e, ||J^T e||_inf and ||p||^2.
* The symmetry of J^T J is again exploited for speed
*/
if((updp && nu>16) || updjac==K){ /* compute difference approximation to J */
if(using_ffdif){ /* use forward differences */
LEVMAR_FDIF_FORW_JAC_APPROX(func, p, hx, wrk, delta, jac, m, n, adata);
++njap; nfev+=m;
}
else{ /* use central differences */
LEVMAR_FDIF_CENT_JAC_APPROX(func, p, wrk, wrk2, delta, jac, m, n, adata);
++njap; nfev+=2*m;
}
nu=2; updjac=0; updp=0; newjac=1;
}
if(newjac){ /* Jacobian has changed, recompute J^T J, J^t e, etc */
newjac=0;
/* J^T J, J^T e */
if(nm<=__BLOCKSZ__SQ){ // this is a small problem
/* J^T*J_ij = \sum_l J^T_il * J_lj = \sum_l J_li * J_lj.
* Thus, the product J^T J can be computed using an outer loop for
* l that adds J_li*J_lj to each element ij of the result. Note that
* with this scheme, the accesses to J and JtJ are always along rows,
* therefore induces less cache misses compared to the straightforward
* algorithm for computing the product (i.e., l loop is innermost one).
* A similar scheme applies to the computation of J^T e.
* However, for large minimization problems (i.e., involving a large number
* of unknowns and measurements) for which J/J^T J rows are too large to
* fit in the L1 cache, even this scheme incures many cache misses. In
* such cases, a cache-efficient blocking scheme is preferable.
*
* Thanks to John Nitao of Lawrence Livermore Lab for pointing out this
* performance problem.
*
* Note that the non-blocking algorithm is faster on small
* problems since in this case it avoids the overheads of blocking.
*/
register int l;
register LM_REAL alpha, *jaclm, *jacTjacim;
/* looping downwards saves a few computations */
for(i=m*m; i-->0; )
jacTjac[i]=0.0;
for(i=m; i-->0; )
jacTe[i]=0.0;
for(l=n; l-->0; ){
jaclm=jac+l*m;
for(i=m; i-->0; ){
jacTjacim=jacTjac+i*m;
alpha=jaclm[i]; //jac[l*m+i];
for(j=i+1; j-->0; ) /* j<=i computes lower triangular part only */
jacTjacim[j]+=jaclm[j]*alpha; //jacTjac[i*m+j]+=jac[l*m+j]*alpha
/* J^T e */
jacTe[i]+=alpha*e[l];
}
}
for(i=m; i-->0; ) /* copy to upper part */
for(j=i+1; j<m; ++j)
jacTjac[i*m+j]=jacTjac[j*m+i];
}
else{ // this is a large problem
/* Cache efficient computation of J^T J based on blocking
*/
LEVMAR_TRANS_MAT_MAT_MULT(jac, jacTjac, n, m);
/* cache efficient computation of J^T e */
for(i=0; i<m; ++i)
jacTe[i]=0.0;
for(i=0; i<n; ++i){
register LM_REAL *jacrow;
for(l=0, jacrow=jac+i*m, tmp=e[i]; l<m; ++l)
jacTe[l]+=jacrow[l]*tmp;
}
}
/* Compute ||J^T e||_inf and ||p||^2 */
for(i=0, p_L2=jacTe_inf=0.0; i<m; ++i){
if(jacTe_inf < (tmp=FABS(jacTe[i]))) jacTe_inf=tmp;
diag_jacTjac[i]=jacTjac[i*m+i]; /* save diagonal entries so that augmentation can be later canceled */
p_L2+=p[i]*p[i];
}
//p_L2=sqrt(p_L2);
}
#if 0
if(!(k%100)){
printf("Current estimate: ");
for(i=0; i<m; ++i)
printf("%.9g ", p[i]);
printf("-- errors %.9g %0.9g\n", jacTe_inf, p_eL2);
}
#endif
/* check for convergence */
if((jacTe_inf <= eps1)){
Dp_L2=0.0; /* no increment for p in this case */
stop=1;
break;
}
/* compute initial damping factor */
if(k==0){
for(i=0, tmp=LM_REAL_MIN; i<m; ++i)
if(diag_jacTjac[i]>tmp) tmp=diag_jacTjac[i]; /* find max diagonal element */
mu=tau*tmp;
}
/* determine increment using adaptive damping */
/* augment normal equations */
for(i=0; i<m; ++i)
jacTjac[i*m+i]+=mu;
/* solve augmented equations */
#ifdef HAVE_LAPACK
/* 7 alternatives are available: LU, Cholesky + Cholesky with PLASMA, LDLt, 2 variants of QR decomposition and SVD.
* For matrices with dimensions of at least a few hundreds, the PLASMA implementation of Cholesky is the fastest.
* From the serial solvers, Cholesky is the fastest but might occasionally be inapplicable due to numerical round-off;
* QR is slower but more robust; SVD is the slowest but most robust; LU is quite robust but
* slower than LDLt; LDLt offers a good tradeoff between robustness and speed
*/
issolved=AX_EQ_B_BK(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_BK;
//issolved=AX_EQ_B_LU(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_LU;
//issolved=AX_EQ_B_CHOL(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_CHOL;
#ifdef HAVE_PLASMA
//issolved=AX_EQ_B_PLASMA_CHOL(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_PLASMA_CHOL;
#endif
//issolved=AX_EQ_B_QR(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_QR;
//issolved=AX_EQ_B_QRLS(jacTjac, jacTe, Dp, m, m); ++nlss; linsolver=(int (*)(LM_REAL *A, LM_REAL *B, LM_REAL *x, int m))AX_EQ_B_QRLS;
//issolved=AX_EQ_B_SVD(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_SVD;
#else
/* use the LU included with levmar */
issolved=AX_EQ_B_LU(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_LU;
#endif /* HAVE_LAPACK */
if(issolved){
/* compute p's new estimate and ||Dp||^2 */
for(i=0, Dp_L2=0.0; i<m; ++i){
pDp[i]=p[i] + (tmp=Dp[i]);
Dp_L2+=tmp*tmp;
}
//Dp_L2=sqrt(Dp_L2);
if(Dp_L2<=eps2_sq*p_L2){ /* relative change in p is small, stop */
//if(Dp_L2<=eps2*(p_L2 + eps2)){ /* relative change in p is small, stop */
stop=2;
break;
}
if(Dp_L2>=(p_L2+eps2)/(LM_CNST(EPSILON)*LM_CNST(EPSILON))){ /* almost singular */
//if(Dp_L2>=(p_L2+eps2)/LM_CNST(EPSILON)){ /* almost singular */
stop=4;
break;
}
(*func)(pDp, wrk, m, n, adata); ++nfev; /* evaluate function at p + Dp */
/* compute ||e(pDp)||_2 */
/* ### wrk2=x-wrk, pDp_eL2=||wrk2|| */
#if 1
pDp_eL2=LEVMAR_L2NRMXMY(wrk2, x, wrk, n);
#else
for(i=0, pDp_eL2=0.0; i<n; ++i){
wrk2[i]=tmp=x[i]-wrk[i];
pDp_eL2+=tmp*tmp;
}
#endif
if(!LM_FINITE(pDp_eL2)){ /* sum of squares is not finite, most probably due to a user error.
* This check makes sure that the loop terminates early in the case
* of invalid input. Thanks to Steve Danauskas for suggesting it
*/
stop=7;
break;
}
dF=p_eL2-pDp_eL2;
if(updp || dF>0){ /* update jac */
for(i=0; i<n; ++i){
for(l=0, tmp=0.0; l<m; ++l)
tmp+=jac[i*m+l]*Dp[l]; /* (J * Dp)[i] */
tmp=(wrk[i] - hx[i] - tmp)/Dp_L2; /* (f(p+dp)[i] - f(p)[i] - (J * Dp)[i])/(dp^T*dp) */
for(j=0; j<m; ++j)
jac[i*m+j]+=tmp*Dp[j];
}
++updjac;
newjac=1;
}
for(i=0, dL=0.0; i<m; ++i)
dL+=Dp[i]*(mu*Dp[i]+jacTe[i]);
if(dL>0.0 && dF>0.0){ /* reduction in error, increment is accepted */
tmp=(LM_CNST(2.0)*dF/dL-LM_CNST(1.0));
tmp=LM_CNST(1.0)-tmp*tmp*tmp;
mu=mu*( (tmp>=LM_CNST(ONE_THIRD))? tmp : LM_CNST(ONE_THIRD) );
nu=2;
for(i=0 ; i<m; ++i) /* update p's estimate */
p[i]=pDp[i];
for(i=0; i<n; ++i){ /* update e, hx and ||e||_2 */
e[i]=wrk2[i]; //x[i]-wrk[i];
hx[i]=wrk[i];
}
p_eL2=pDp_eL2;
updp=1;
continue;
}
}
/* if this point is reached, either the linear system could not be solved or
* the error did not reduce; in any case, the increment must be rejected
*/
mu*=nu;
nu2=nu<<1; // 2*nu;
if(nu2<=nu){ /* nu has wrapped around (overflown). Thanks to Frank Jordan for spotting this case */
stop=5;
break;
}
nu=nu2;
for(i=0; i<m; ++i) /* restore diagonal J^T J entries */
jacTjac[i*m+i]=diag_jacTjac[i];
}
if(k>=itmax) stop=3;
for(i=0; i<m; ++i) /* restore diagonal J^T J entries */
jacTjac[i*m+i]=diag_jacTjac[i];
if(info){
info[0]=init_p_eL2;
info[1]=p_eL2;
info[2]=jacTe_inf;
info[3]=Dp_L2;
for(i=0, tmp=LM_REAL_MIN; i<m; ++i)
if(tmp<jacTjac[i*m+i]) tmp=jacTjac[i*m+i];
info[4]=mu/tmp;
info[5]=(LM_REAL)k;
info[6]=(LM_REAL)stop;
info[7]=(LM_REAL)nfev;
info[8]=(LM_REAL)njap;
info[9]=(LM_REAL)nlss;
}
/* covariance matrix */
if(covar){
LEVMAR_COVAR(jacTjac, covar, p_eL2, m, n);
}
if(freework) free(work);
#ifdef LINSOLVERS_RETAIN_MEMORY
if(linsolver) (*linsolver)(NULL, NULL, NULL, 0);
#endif
return (stop!=4 && stop!=7)? k : LM_ERROR;
}
/* undefine everything. THIS MUST REMAIN AT THE END OF THE FILE */
#undef LEVMAR_DER
#undef LEVMAR_DIF
#undef LEVMAR_FDIF_FORW_JAC_APPROX
#undef LEVMAR_FDIF_CENT_JAC_APPROX
#undef LEVMAR_COVAR
#undef LEVMAR_TRANS_MAT_MAT_MULT
#undef LEVMAR_L2NRMXMY
#undef AX_EQ_B_LU
#undef AX_EQ_B_CHOL
#undef AX_EQ_B_PLASMA_CHOL
#undef AX_EQ_B_QR
#undef AX_EQ_B_QRLS
#undef AX_EQ_B_SVD
#undef AX_EQ_B_BK

87
levmar/lmbc.c Normal file
View File

@@ -0,0 +1,87 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-05 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/********************************************************************************
* Box-constrained Levenberg-Marquardt nonlinear minimization. The same core code
* is used with appropriate #defines to derive single and double precision versions,
* see also lmbc_core.c
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "levmar.h"
#include "compiler.h"
#include "misc.h"
#define EPSILON 1E-12
#define ONE_THIRD 0.3333333334 /* 1.0/3.0 */
#define _LSITMAX_ 150 /* max #iterations for line search */
#define _POW_ 2.1
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define LM_REAL_MAX FLT_MAX
#define LM_REAL_MIN -FLT_MAX
#define LM_REAL_EPSILON FLT_EPSILON
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#include "lmbc_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_MIN
#undef LM_REAL_EPSILON
#undef __SUBCNST
#undef LM_CNST
#endif /* LM_SNGL_PREC */
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_REAL_MAX DBL_MAX
#define LM_REAL_MIN -DBL_MAX
#define LM_REAL_EPSILON DBL_EPSILON
#define LM_CNST(x) (x)
#include "lmbc_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_MIN
#undef LM_REAL_EPSILON
#undef LM_CNST
#endif /* LM_DBL_PREC */

1154
levmar/lmbc_core.c Normal file

File diff suppressed because it is too large Load Diff

87
levmar/lmblec.c Normal file
View File

@@ -0,0 +1,87 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-06 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/********************************************************************************
* combined box and linear equation constraints Levenberg-Marquardt nonlinear
* minimization. The same core code is used with appropriate #defines to derive
* single and double precision versions, see also lmblec_core.c
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "levmar.h"
#include "misc.h"
#ifndef HAVE_LAPACK
#ifdef _MSC_VER
#pragma message("Combined box and linearly constrained optimization requires LAPACK and was not compiled!")
#else
#warning Combined box and linearly constrained optimization requires LAPACK and was not compiled!
#endif // _MSC_VER
#else // LAPACK present
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define LM_REAL_MAX FLT_MAX
#define LM_REAL_MIN -FLT_MAX
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#include "lmblec_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_MIN
#undef __SUBCNST
#undef LM_CNST
#endif /* LM_SNGL_PREC */
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_REAL_MAX DBL_MAX
#define LM_REAL_MIN -DBL_MAX
#define LM_CNST(x) (x)
#include "lmblec_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_MIN
#undef LM_CNST
#endif /* LM_DBL_PREC */
#endif /* HAVE_LAPACK */

413
levmar/lmblec_core.c Normal file
View File

@@ -0,0 +1,413 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-06 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
* This file implements combined box and linear equation constraints.
*
* Note that the algorithm implementing linearly constrained minimization does
* so by a change in parameters that transforms the original program into an
* unconstrained one. To employ the same idea for implementing box & linear
* constraints would require the transformation of box constraints on the
* original parameters to box constraints for the new parameter set. This
* being impossible, a different approach is used here for finding the minimum.
* The trick is to remove the box constraints by augmenting the function to
* be fitted with penalty terms and then solve the resulting problem (which
* involves linear constrains only) with the functions in lmlec.c
*
* More specifically, for the constraint a<=x[i]<=b to hold, the term C[i]=
* (2*x[i]-(a+b))/(b-a) should be within [-1, 1]. This is enforced by adding
* the penalty term w[i]*max((C[i])^2-1, 0) to the objective function, where
* w[i] is a large weight. In the case of constraints of the form a<=x[i],
* the term C[i]=a-x[i] has to be non positive, thus the penalty term is
* w[i]*max(C[i], 0). If x[i]<=b, C[i]=x[i]-b has to be non negative and
* the penalty is w[i]*max(C[i], 0). The derivatives needed for the Jacobian
* are as follows:
* For the constraint a<=x[i]<=b: 4*(2*x[i]-(a+b))/(b-a)^2 if x[i] not in [a, b],
* 0 otherwise
* For the constraint a<=x[i]: -1 if x[i]<=a, 0 otherwise
* For the constraint x[i]<=b: 1 if b<=x[i], 0 otherwise
*
* Note that for the above to work, the weights w[i] should be large enough;
* depending on your minimization problem, the default values might need some
* tweaking (see arg "wghts" below).
*******************************************************************************/
#ifndef LM_REAL // not included by lmblec.c
#error This file should not be compiled directly!
#endif
#define __MAX__(x, y) (((x)>=(y))? (x) : (y))
#define __BC_WEIGHT__ LM_CNST(1E+04)
#define __BC_INTERVAL__ 0
#define __BC_LOW__ 1
#define __BC_HIGH__ 2
/* precision-specific definitions */
#define LEVMAR_BOX_CHECK LM_ADD_PREFIX(levmar_box_check)
#define LMBLEC_DATA LM_ADD_PREFIX(lmblec_data)
#define LMBLEC_FUNC LM_ADD_PREFIX(lmblec_func)
#define LMBLEC_JACF LM_ADD_PREFIX(lmblec_jacf)
#define LEVMAR_LEC_DER LM_ADD_PREFIX(levmar_lec_der)
#define LEVMAR_LEC_DIF LM_ADD_PREFIX(levmar_lec_dif)
#define LEVMAR_BLEC_DER LM_ADD_PREFIX(levmar_blec_der)
#define LEVMAR_BLEC_DIF LM_ADD_PREFIX(levmar_blec_dif)
#define LEVMAR_COVAR LM_ADD_PREFIX(levmar_covar)
struct LMBLEC_DATA{
LM_REAL *x, *lb, *ub, *w;
int *bctype;
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata);
void (*jacf)(LM_REAL *p, LM_REAL *jac, int m, int n, void *adata);
void *adata;
};
/* augmented measurements */
static void LMBLEC_FUNC(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata)
{
struct LMBLEC_DATA *data=(struct LMBLEC_DATA *)adata;
int nn;
register int i, j, *typ;
register LM_REAL *lb, *ub, *w, tmp;
nn=n-m;
lb=data->lb;
ub=data->ub;
w=data->w;
typ=data->bctype;
(*(data->func))(p, hx, m, nn, data->adata);
for(i=nn, j=0; i<n; ++i, ++j){
switch(typ[j]){
case __BC_INTERVAL__:
tmp=(LM_CNST(2.0)*p[j]-(lb[j]+ub[j]))/(ub[j]-lb[j]);
hx[i]=w[j]*__MAX__(tmp*tmp-LM_CNST(1.0), LM_CNST(0.0));
break;
case __BC_LOW__:
hx[i]=w[j]*__MAX__(lb[j]-p[j], LM_CNST(0.0));
break;
case __BC_HIGH__:
hx[i]=w[j]*__MAX__(p[j]-ub[j], LM_CNST(0.0));
break;
}
}
}
/* augmented Jacobian */
static void LMBLEC_JACF(LM_REAL *p, LM_REAL *jac, int m, int n, void *adata)
{
struct LMBLEC_DATA *data=(struct LMBLEC_DATA *)adata;
int nn, *typ;
register int i, j;
register LM_REAL *lb, *ub, *w, tmp;
nn=n-m;
lb=data->lb;
ub=data->ub;
w=data->w;
typ=data->bctype;
(*(data->jacf))(p, jac, m, nn, data->adata);
/* clear all extra rows */
for(i=nn*m; i<n*m; ++i)
jac[i]=0.0;
for(i=nn, j=0; i<n; ++i, ++j){
switch(typ[j]){
case __BC_INTERVAL__:
if(lb[j]<=p[j] && p[j]<=ub[j])
continue; // corresp. jac element already 0
/* out of interval */
tmp=ub[j]-lb[j];
tmp=LM_CNST(4.0)*(LM_CNST(2.0)*p[j]-(lb[j]+ub[j]))/(tmp*tmp);
jac[i*m+j]=w[j]*tmp;
break;
case __BC_LOW__: // (lb[j]<=p[j])? 0.0 : -1.0;
if(lb[j]<=p[j])
continue; // corresp. jac element already 0
/* smaller than lower bound */
jac[i*m+j]=-w[j];
break;
case __BC_HIGH__: // (p[j]<=ub[j])? 0.0 : 1.0;
if(p[j]<=ub[j])
continue; // corresp. jac element already 0
/* greater than upper bound */
jac[i*m+j]=w[j];
break;
}
}
}
/*
* This function seeks the parameter vector p that best describes the measurements
* vector x under box & linear constraints.
* More precisely, given a vector function func : R^m --> R^n with n>=m,
* it finds p s.t. func(p) ~= x, i.e. the squared second order (i.e. L2) norm of
* e=x-func(p) is minimized under the constraints lb[i]<=p[i]<=ub[i] and A p=b;
* A is kxm, b kx1. Note that this function DOES NOT check the satisfiability of
* the specified box and linear equation constraints.
* If no lower bound constraint applies for p[i], use -DBL_MAX/-FLT_MAX for lb[i];
* If no upper bound constraint applies for p[i], use DBL_MAX/FLT_MAX for ub[i].
*
* This function requires an analytic Jacobian. In case the latter is unavailable,
* use LEVMAR_BLEC_DIF() bellow
*
* Returns the number of iterations (>=0) if successful, LM_ERROR if failed
*
* For more details on the algorithm implemented by this function, please refer to
* the comments in the top of this file.
*
*/
int LEVMAR_BLEC_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata), /* function to evaluate the Jacobian \part x / \part p */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
LM_REAL *lb, /* I: vector of lower bounds. If NULL, no lower bounds apply */
LM_REAL *ub, /* I: vector of upper bounds. If NULL, no upper bounds apply */
LM_REAL *A, /* I: constraints matrix, kxm */
LM_REAL *b, /* I: right hand constraints vector, kx1 */
int k, /* I: number of constraints (i.e. A's #rows) */
LM_REAL *wghts, /* mx1 weights for penalty terms, defaults used if NULL */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[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_REAL info[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_BLEC_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
*/
{
struct LMBLEC_DATA data;
int ret;
LM_REAL locinfo[LM_INFO_SZ];
register int i;
if(!jacf){
fprintf(stderr, RCAT("No function specified for computing the Jacobian in ", LEVMAR_BLEC_DER)
RCAT("().\nIf no such function is available, use ", LEVMAR_BLEC_DIF) RCAT("() rather than ", LEVMAR_BLEC_DER) "()\n");
return LM_ERROR;
}
if(!lb && !ub){
fprintf(stderr, RCAT(LCAT(LEVMAR_BLEC_DER, "(): lower and upper bounds for box constraints cannot be both NULL, use "),
LEVMAR_LEC_DER) "() in this case!\n");
return LM_ERROR;
}
if(!LEVMAR_BOX_CHECK(lb, ub, m)){
fprintf(stderr, LCAT(LEVMAR_BLEC_DER, "(): at least one lower bound exceeds the upper one\n"));
return LM_ERROR;
}
/* measurement vector needs to be extended by m */
if(x){ /* nonzero x */
data.x=(LM_REAL *)malloc((n+m)*sizeof(LM_REAL));
if(!data.x){
fprintf(stderr, LCAT(LEVMAR_BLEC_DER, "(): memory allocation request #1 failed\n"));
return LM_ERROR;
}
for(i=0; i<n; ++i)
data.x[i]=x[i];
for(i=n; i<n+m; ++i)
data.x[i]=0.0;
}
else
data.x=NULL;
data.w=(LM_REAL *)malloc(m*sizeof(LM_REAL) + m*sizeof(int)); /* should be arranged in that order for proper doubles alignment */
if(!data.w){
fprintf(stderr, LCAT(LEVMAR_BLEC_DER, "(): memory allocation request #2 failed\n"));
if(data.x) free(data.x);
return LM_ERROR;
}
data.bctype=(int *)(data.w+m);
/* note: at this point, one of lb, ub are not NULL */
for(i=0; i<m; ++i){
data.w[i]=(!wghts)? __BC_WEIGHT__ : wghts[i];
if(!lb) data.bctype[i]=__BC_HIGH__;
else if(!ub) data.bctype[i]=__BC_LOW__;
else if(ub[i]!=LM_REAL_MAX && lb[i]!=LM_REAL_MIN) data.bctype[i]=__BC_INTERVAL__;
else if(lb[i]!=LM_REAL_MIN) data.bctype[i]=__BC_LOW__;
else data.bctype[i]=__BC_HIGH__;
}
data.lb=lb;
data.ub=ub;
data.func=func;
data.jacf=jacf;
data.adata=adata;
if(!info) info=locinfo; /* make sure that LEVMAR_LEC_DER() is called with non-null info */
ret=LEVMAR_LEC_DER(LMBLEC_FUNC, LMBLEC_JACF, p, data.x, m, n+m, A, b, k, itmax, opts, info, work, covar, (void *)&data);
if(data.x) free(data.x);
free(data.w);
return ret;
}
/* Similar to the LEVMAR_BLEC_DER() function above, except that the Jacobian is approximated
* with the aid of finite differences (forward or central, see the comment for the opts argument)
*/
int LEVMAR_BLEC_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
LM_REAL *lb, /* I: vector of lower bounds. If NULL, no lower bounds apply */
LM_REAL *ub, /* I: vector of upper bounds. If NULL, no upper bounds apply */
LM_REAL *A, /* I: constraints matrix, kxm */
LM_REAL *b, /* I: right hand constraints vector, kx1 */
int k, /* I: number of constraints (i.e. A's #rows) */
LM_REAL *wghts, /* mx1 weights for penalty terms, defaults used if NULL */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[5], /* I: opts[0-3] = minim. options [\mu, \epsilon1, \epsilon2, \epsilon3, \delta]. Respectively the
* 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_REAL info[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_BLEC_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
*/
{
struct LMBLEC_DATA data;
int ret;
register int i;
LM_REAL locinfo[LM_INFO_SZ];
if(!lb && !ub){
fprintf(stderr, RCAT(LCAT(LEVMAR_BLEC_DIF, "(): lower and upper bounds for box constraints cannot be both NULL, use "),
LEVMAR_LEC_DIF) "() in this case!\n");
return LM_ERROR;
}
if(!LEVMAR_BOX_CHECK(lb, ub, m)){
fprintf(stderr, LCAT(LEVMAR_BLEC_DER, "(): at least one lower bound exceeds the upper one\n"));
return LM_ERROR;
}
/* measurement vector needs to be extended by m */
if(x){ /* nonzero x */
data.x=(LM_REAL *)malloc((n+m)*sizeof(LM_REAL));
if(!data.x){
fprintf(stderr, LCAT(LEVMAR_BLEC_DER, "(): memory allocation request #1 failed\n"));
return LM_ERROR;
}
for(i=0; i<n; ++i)
data.x[i]=x[i];
for(i=n; i<n+m; ++i)
data.x[i]=0.0;
}
else
data.x=NULL;
data.w=(LM_REAL *)malloc(m*sizeof(LM_REAL) + m*sizeof(int)); /* should be arranged in that order for proper doubles alignment */
if(!data.w){
fprintf(stderr, LCAT(LEVMAR_BLEC_DER, "(): memory allocation request #2 failed\n"));
if(data.x) free(data.x);
return LM_ERROR;
}
data.bctype=(int *)(data.w+m);
/* note: at this point, one of lb, ub are not NULL */
for(i=0; i<m; ++i){
data.w[i]=(!wghts)? __BC_WEIGHT__ : wghts[i];
if(!lb) data.bctype[i]=__BC_HIGH__;
else if(!ub) data.bctype[i]=__BC_LOW__;
else if(ub[i]!=LM_REAL_MAX && lb[i]!=LM_REAL_MIN) data.bctype[i]=__BC_INTERVAL__;
else if(lb[i]!=LM_REAL_MIN) data.bctype[i]=__BC_LOW__;
else data.bctype[i]=__BC_HIGH__;
}
data.lb=lb;
data.ub=ub;
data.func=func;
data.jacf=NULL;
data.adata=adata;
if(!info) info=locinfo; /* make sure that LEVMAR_LEC_DIF() is called with non-null info */
ret=LEVMAR_LEC_DIF(LMBLEC_FUNC, p, data.x, m, n+m, A, b, k, itmax, opts, info, work, covar, (void *)&data);
if(data.x) free(data.x);
free(data.w);
return ret;
}
/* undefine all. THIS MUST REMAIN AT THE END OF THE FILE */
#undef LEVMAR_BOX_CHECK
#undef LMBLEC_DATA
#undef LMBLEC_FUNC
#undef LMBLEC_JACF
#undef LEVMAR_COVAR
#undef LEVMAR_LEC_DER
#undef LEVMAR_LEC_DIF
#undef LEVMAR_BLEC_DER
#undef LEVMAR_BLEC_DIF

89
levmar/lmbleic.c Normal file
View File

@@ -0,0 +1,89 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2009 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
* Wrappers for linear inequality constrained Levenberg-Marquardt minimization.
* The same core code is used with appropriate #defines to derive single and
* double precision versions, see also lmbleic_core.c
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "levmar.h"
#include "misc.h"
#ifndef HAVE_LAPACK
#ifdef _MSC_VER
#pragma message("Linear inequalities constrained optimization requires LAPACK and was not compiled!")
#else
#warning Linear inequalities constrained optimization requires LAPACK and was not compiled!
#endif // _MSC_VER
#else // LAPACK present
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define LM_REAL_MAX FLT_MAX
#define LM_REAL_MIN -FLT_MAX
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#include "lmbleic_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_MIN
#undef __SUBCNST
#undef LM_CNST
#endif /* LM_SNGL_PREC */
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_REAL_MAX DBL_MAX
#define LM_REAL_MIN -DBL_MAX
#define LM_CNST(x) (x)
#include "lmbleic_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_MIN
#undef LM_CNST
#endif /* LM_DBL_PREC */
#endif /* HAVE_LAPACK */

506
levmar/lmbleic_core.c Normal file
View File

@@ -0,0 +1,506 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2009 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef LM_REAL // not included by lmbleic.c
#error This file should not be compiled directly!
#endif
/* precision-specific definitions */
#define LMBLEIC_DATA LM_ADD_PREFIX(lmbleic_data)
#define LMBLEIC_ELIM LM_ADD_PREFIX(lmbleic_elim)
#define LMBLEIC_FUNC LM_ADD_PREFIX(lmbleic_func)
#define LMBLEIC_JACF LM_ADD_PREFIX(lmbleic_jacf)
#define LEVMAR_BLEIC_DER LM_ADD_PREFIX(levmar_bleic_der)
#define LEVMAR_BLEIC_DIF LM_ADD_PREFIX(levmar_bleic_dif)
#define LEVMAR_BLIC_DER LM_ADD_PREFIX(levmar_blic_der)
#define LEVMAR_BLIC_DIF LM_ADD_PREFIX(levmar_blic_dif)
#define LEVMAR_LEIC_DER LM_ADD_PREFIX(levmar_leic_der)
#define LEVMAR_LEIC_DIF LM_ADD_PREFIX(levmar_leic_dif)
#define LEVMAR_LIC_DER LM_ADD_PREFIX(levmar_lic_der)
#define LEVMAR_LIC_DIF LM_ADD_PREFIX(levmar_lic_dif)
#define LEVMAR_BLEC_DER LM_ADD_PREFIX(levmar_blec_der)
#define LEVMAR_BLEC_DIF LM_ADD_PREFIX(levmar_blec_dif)
#define LEVMAR_TRANS_MAT_MAT_MULT LM_ADD_PREFIX(levmar_trans_mat_mat_mult)
#define LEVMAR_COVAR LM_ADD_PREFIX(levmar_covar)
#define LEVMAR_FDIF_FORW_JAC_APPROX LM_ADD_PREFIX(levmar_fdif_forw_jac_approx)
struct LMBLEIC_DATA{
LM_REAL *jac;
int nineqcnstr; // #inequality constraints
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata);
void (*jacf)(LM_REAL *p, LM_REAL *jac, int m, int n, void *adata);
void *adata;
};
/* wrapper ensuring that the user-supplied function is called with the right number of variables (i.e. m) */
static void LMBLEIC_FUNC(LM_REAL *pext, LM_REAL *hx, int mm, int n, void *adata)
{
struct LMBLEIC_DATA *data=(struct LMBLEIC_DATA *)adata;
int m;
m=mm-data->nineqcnstr;
(*(data->func))(pext, hx, m, n, data->adata);
}
/* wrapper for computing the Jacobian at pext. The Jacobian is nxmm */
static void LMBLEIC_JACF(LM_REAL *pext, LM_REAL *jacext, int mm, int n, void *adata)
{
struct LMBLEIC_DATA *data=(struct LMBLEIC_DATA *)adata;
int m;
register int i, j;
LM_REAL *jac, *jacim, *jacextimm;
m=mm-data->nineqcnstr;
jac=data->jac;
(*(data->jacf))(pext, jac, m, n, data->adata);
for(i=0; i<n; ++i){
jacextimm=jacext+i*mm;
jacim=jac+i*m;
for(j=0; j<m; ++j)
jacextimm[j]=jacim[j]; //jacext[i*mm+j]=jac[i*m+j];
for(j=m; j<mm; ++j)
jacextimm[j]=0.0; //jacext[i*mm+j]=0.0;
}
}
/*
* This function is similar to LEVMAR_DER except that the minimization is
* performed subject to the box constraints lb[i]<=p[i]<=ub[i], the linear
* equation constraints A*p=b, A being k1xm, b k1x1, and the linear inequality
* constraints C*p>=d, C being k2xm, d k2x1.
*
* The inequalities are converted to equations by introducing surplus variables,
* i.e. c^T*p >= d becomes c^T*p - y = d, with y>=0. To transform all inequalities
* to equations, a total of k2 surplus variables are introduced; a problem with only
* box and linear constraints results then and is solved with LEVMAR_BLEC_DER()
* Note that opposite direction inequalities should be converted to the desired
* direction by negating, i.e. c^T*p <= d becomes -c^T*p >= -d
*
* This function requires an analytic Jacobian. In case the latter is unavailable,
* use LEVMAR_BLEIC_DIF() bellow
*
*/
int LEVMAR_BLEIC_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata), /* function to evaluate the Jacobian \part x / \part p */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
LM_REAL *lb, /* I: vector of lower bounds. If NULL, no lower bounds apply */
LM_REAL *ub, /* I: vector of upper bounds. If NULL, no upper bounds apply */
LM_REAL *A, /* I: equality constraints matrix, k1xm. If NULL, no linear equation constraints apply */
LM_REAL *b, /* I: right hand constraints vector, k1x1 */
int k1, /* I: number of constraints (i.e. A's #rows) */
LM_REAL *C, /* I: inequality constraints matrix, k2xm */
LM_REAL *d, /* I: right hand constraints vector, k2x1 */
int k2, /* I: number of inequality constraints (i.e. C's #rows) */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[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_REAL info[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
*/
{
struct LMBLEIC_DATA data;
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
int mm, ret, k12;
register int i, j, ii;
register LM_REAL tmp;
LM_REAL locinfo[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");
return LM_ERROR;
}
if(!C || !d){
fprintf(stderr, RCAT(LCAT(LEVMAR_BLEIC_DER, "(): missing inequality constraints, use "), LEVMAR_BLEC_DER) "() in this case!\n");
return LM_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);
return LM_ERROR;
}
k12=k1+k2;
ptr=(LM_REAL *)malloc((3*mm + k12*mm + k12 + n*m + (covar? mm*mm : 0))*sizeof(LM_REAL));
if(!ptr){
fprintf(stderr, LCAT(LEVMAR_BLEIC_DER, "(): memory allocation request failed\n"));
return LM_ERROR;
}
pext=ptr;
lbext=pext+mm;
ubext=lbext+mm;
Aext=ubext+mm;
bext=Aext+k12*mm;
data.jac=bext+k12;
covext=covar? data.jac+n*m : NULL;
data.nineqcnstr=k2;
data.func=func;
data.jacf=jacf;
data.adata=adata;
/* compute y s.t. C*p - y=d, i.e. y=C*p-d.
* y is stored in the last k2 elements of pext
*/
for(i=0; i<k2; ++i){
for(j=0, tmp=0.0; j<m; ++j)
tmp+=C[i*m+j]*p[j];
pext[j=i+m]=tmp-d[i];
/* surplus variables must be >=0 */
lbext[j]=0.0;
ubext[j]=LM_REAL_MAX;
}
/* set the first m elements of pext equal to p */
for(i=0; i<m; ++i){
pext[i]=p[i];
lbext[i]=lb? lb[i] : LM_REAL_MIN;
ubext[i]=ub? ub[i] : LM_REAL_MAX;
}
/* setup the constraints matrix */
/* original linear equation constraints */
for(i=0; i<k1; ++i){
for(j=0; j<m; ++j)
Aext[i*mm+j]=A[i*m+j];
for(j=m; j<mm; ++j)
Aext[i*mm+j]=0.0;
bext[i]=b[i];
}
/* linear equation constraints resulting from surplus variables */
for(i=0, ii=k1; i<k2; ++i, ++ii){
for(j=0; j<m; ++j)
Aext[ii*mm+j]=C[i*m+j];
for(j=m; j<mm; ++j)
Aext[ii*mm+j]=0.0;
Aext[ii*mm+m+i]=-1.0;
bext[ii]=d[i];
}
if(!info) info=locinfo; /* make sure that LEVMAR_BLEC_DER() is called with non-null info */
/* note that the default weights for the penalty terms are being used below */
ret=LEVMAR_BLEC_DER(LMBLEIC_FUNC, LMBLEIC_JACF, pext, x, mm, n, lbext, ubext, Aext, bext, k12, NULL, itmax, opts, info, work, covext, (void *)&data);
/* copy back the minimizer */
for(i=0; i<m; ++i)
p[i]=pext[i];
#if 0
printf("Surplus variables for the minimizer:\n");
for(i=m; i<mm; ++i)
printf("%g ", pext[i]);
printf("\n\n");
#endif
if(covar){
for(i=0; i<m; ++i){
for(j=0; j<m; ++j)
covar[i*m+j]=covext[i*mm+j];
}
}
free(ptr);
return ret;
}
/* Similar to the LEVMAR_BLEIC_DER() function above, except that the Jacobian is approximated
* with the aid of finite differences (forward or central, see the comment for the opts argument)
*/
int LEVMAR_BLEIC_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
LM_REAL *lb, /* I: vector of lower bounds. If NULL, no lower bounds apply */
LM_REAL *ub, /* I: vector of upper bounds. If NULL, no upper bounds apply */
LM_REAL *A, /* I: equality constraints matrix, k1xm. If NULL, no linear equation constraints apply */
LM_REAL *b, /* I: right hand constraints vector, k1x1 */
int k1, /* I: number of constraints (i.e. A's #rows) */
LM_REAL *C, /* I: inequality constraints matrix, k2xm */
LM_REAL *d, /* I: right hand constraints vector, k2x1 */
int k2, /* I: number of inequality constraints (i.e. C's #rows) */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[5], /* I: opts[0-3] = minim. options [\mu, \epsilon1, \epsilon2, \epsilon3, \delta]. Respectively the
* 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_REAL info[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
*/
{
struct LMBLEIC_DATA data;
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
int mm, ret, k12;
register int i, j, ii;
register LM_REAL tmp;
LM_REAL locinfo[LM_INFO_SZ];
if(!C || !d){
fprintf(stderr, RCAT(LCAT(LEVMAR_BLEIC_DIF, "(): missing inequality constraints, use "), LEVMAR_BLEC_DIF) "() in this case!\n");
return LM_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);
return LM_ERROR;
}
k12=k1+k2;
ptr=(LM_REAL *)malloc((3*mm + k12*mm + k12 + (covar? mm*mm : 0))*sizeof(LM_REAL));
if(!ptr){
fprintf(stderr, LCAT(LEVMAR_BLEIC_DIF, "(): memory allocation request failed\n"));
return LM_ERROR;
}
pext=ptr;
lbext=pext+mm;
ubext=lbext+mm;
Aext=ubext+mm;
bext=Aext+k12*mm;
data.jac=NULL;
covext=covar? bext+k12 : NULL;
data.nineqcnstr=k2;
data.func=func;
data.jacf=NULL;
data.adata=adata;
/* compute y s.t. C*p - y=d, i.e. y=C*p-d.
* y is stored in the last k2 elements of pext
*/
for(i=0; i<k2; ++i){
for(j=0, tmp=0.0; j<m; ++j)
tmp+=C[i*m+j]*p[j];
pext[j=i+m]=tmp-d[i];
/* surplus variables must be >=0 */
lbext[j]=0.0;
ubext[j]=LM_REAL_MAX;
}
/* set the first m elements of pext equal to p */
for(i=0; i<m; ++i){
pext[i]=p[i];
lbext[i]=lb? lb[i] : LM_REAL_MIN;
ubext[i]=ub? ub[i] : LM_REAL_MAX;
}
/* setup the constraints matrix */
/* original linear equation constraints */
for(i=0; i<k1; ++i){
for(j=0; j<m; ++j)
Aext[i*mm+j]=A[i*m+j];
for(j=m; j<mm; ++j)
Aext[i*mm+j]=0.0;
bext[i]=b[i];
}
/* linear equation constraints resulting from surplus variables */
for(i=0, ii=k1; i<k2; ++i, ++ii){
for(j=0; j<m; ++j)
Aext[ii*mm+j]=C[i*m+j];
for(j=m; j<mm; ++j)
Aext[ii*mm+j]=0.0;
Aext[ii*mm+m+i]=-1.0;
bext[ii]=d[i];
}
if(!info) info=locinfo; /* make sure that LEVMAR_BLEC_DIF() is called with non-null info */
/* note that the default weights for the penalty terms are being used below */
ret=LEVMAR_BLEC_DIF(LMBLEIC_FUNC, pext, x, mm, n, lbext, ubext, Aext, bext, k12, NULL, itmax, opts, info, work, covext, (void *)&data);
/* copy back the minimizer */
for(i=0; i<m; ++i)
p[i]=pext[i];
#if 0
printf("Surplus variables for the minimizer:\n");
for(i=m; i<mm; ++i)
printf("%g ", pext[i]);
printf("\n\n");
#endif
if(covar){
for(i=0; i<m; ++i){
for(j=0; j<m; ++j)
covar[i*m+j]=covext[i*mm+j];
}
}
free(ptr);
return ret;
}
/* convenience wrappers to LEVMAR_BLEIC_DER/LEVMAR_BLEIC_DIF */
/* box & linear inequality constraints */
int LEVMAR_BLIC_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n,
LM_REAL *lb, LM_REAL *ub,
LM_REAL *C, LM_REAL *d, int k2,
int itmax, LM_REAL opts[4], LM_REAL info[LM_INFO_SZ], LM_REAL *work, LM_REAL *covar, void *adata)
{
return LEVMAR_BLEIC_DER(func, jacf, p, x, m, n, lb, ub, NULL, NULL, 0, C, d, k2, itmax, opts, info, work, covar, adata);
}
int LEVMAR_BLIC_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n,
LM_REAL *lb, LM_REAL *ub,
LM_REAL *C, LM_REAL *d, int k2,
int itmax, LM_REAL opts[5], LM_REAL info[LM_INFO_SZ], LM_REAL *work, LM_REAL *covar, void *adata)
{
return LEVMAR_BLEIC_DIF(func, p, x, m, n, lb, ub, NULL, NULL, 0, C, d, k2, itmax, opts, info, work, covar, adata);
}
/* linear equation & inequality constraints */
int LEVMAR_LEIC_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n,
LM_REAL *A, LM_REAL *b, int k1,
LM_REAL *C, LM_REAL *d, int k2,
int itmax, LM_REAL opts[4], LM_REAL info[LM_INFO_SZ], LM_REAL *work, LM_REAL *covar, void *adata)
{
return LEVMAR_BLEIC_DER(func, jacf, p, x, m, n, NULL, NULL, A, b, k1, C, d, k2, itmax, opts, info, work, covar, adata);
}
int LEVMAR_LEIC_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n,
LM_REAL *A, LM_REAL *b, int k1,
LM_REAL *C, LM_REAL *d, int k2,
int itmax, LM_REAL opts[5], LM_REAL info[LM_INFO_SZ], LM_REAL *work, LM_REAL *covar, void *adata)
{
return LEVMAR_BLEIC_DIF(func, p, x, m, n, NULL, NULL, A, b, k1, C, d, k2, itmax, opts, info, work, covar, adata);
}
/* linear inequality constraints */
int LEVMAR_LIC_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n,
LM_REAL *C, LM_REAL *d, int k2,
int itmax, LM_REAL opts[4], LM_REAL info[LM_INFO_SZ], LM_REAL *work, LM_REAL *covar, void *adata)
{
return LEVMAR_BLEIC_DER(func, jacf, p, x, m, n, NULL, NULL, NULL, NULL, 0, C, d, k2, itmax, opts, info, work, covar, adata);
}
int LEVMAR_LIC_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n,
LM_REAL *C, LM_REAL *d, int k2,
int itmax, LM_REAL opts[5], LM_REAL info[LM_INFO_SZ], LM_REAL *work, LM_REAL *covar, void *adata)
{
return LEVMAR_BLEIC_DIF(func, p, x, m, n, NULL, NULL, NULL, NULL, 0, C, d, k2, itmax, opts, info, work, covar, adata);
}
/* undefine all. THIS MUST REMAIN AT THE END OF THE FILE */
#undef LMBLEIC_DATA
#undef LMBLEIC_ELIM
#undef LMBLEIC_FUNC
#undef LMBLEIC_JACF
#undef LEVMAR_FDIF_FORW_JAC_APPROX
#undef LEVMAR_COVAR
#undef LEVMAR_TRANS_MAT_MAT_MULT
#undef LEVMAR_BLEIC_DER
#undef LEVMAR_BLEIC_DIF
#undef LEVMAR_BLIC_DER
#undef LEVMAR_BLIC_DIF
#undef LEVMAR_LEIC_DER
#undef LEVMAR_LEIC_DIF
#undef LEVMAR_LIC_DER
#undef LEVMAR_LIC_DIF
#undef LEVMAR_BLEC_DER
#undef LEVMAR_BLEC_DIF

80
levmar/lmlec.c Normal file
View File

@@ -0,0 +1,80 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-05 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
* Wrappers for linearly constrained Levenberg-Marquardt minimization. The same
* core code is used with appropriate #defines to derive single and double
* precision versions, see also lmlec_core.c
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "levmar.h"
#include "misc.h"
#ifndef HAVE_LAPACK
#ifdef _MSC_VER
#pragma message("Linearly constrained optimization requires LAPACK and was not compiled!")
#else
#warning Linearly constrained optimization requires LAPACK and was not compiled!
#endif // _MSC_VER
#else // LAPACK present
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#include "lmlec_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef __SUBCNST
#undef LM_CNST
#endif /* LM_SNGL_PREC */
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_CNST(x) (x)
#include "lmlec_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_CNST
#endif /* LM_DBL_PREC */
#endif /* HAVE_LAPACK */

656
levmar/lmlec_core.c Normal file
View File

@@ -0,0 +1,656 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-05 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef LM_REAL // not included by lmlec.c
#error This file should not be compiled directly!
#endif
/* precision-specific definitions */
#define LMLEC_DATA LM_ADD_PREFIX(lmlec_data)
#define LMLEC_ELIM LM_ADD_PREFIX(lmlec_elim)
#define LMLEC_FUNC LM_ADD_PREFIX(lmlec_func)
#define LMLEC_JACF LM_ADD_PREFIX(lmlec_jacf)
#define LEVMAR_LEC_DER LM_ADD_PREFIX(levmar_lec_der)
#define LEVMAR_LEC_DIF LM_ADD_PREFIX(levmar_lec_dif)
#define LEVMAR_DER LM_ADD_PREFIX(levmar_der)
#define LEVMAR_DIF LM_ADD_PREFIX(levmar_dif)
#define LEVMAR_TRANS_MAT_MAT_MULT LM_ADD_PREFIX(levmar_trans_mat_mat_mult)
#define LEVMAR_COVAR LM_ADD_PREFIX(levmar_covar)
#define LEVMAR_FDIF_FORW_JAC_APPROX LM_ADD_PREFIX(levmar_fdif_forw_jac_approx)
#define GEQP3 LM_MK_LAPACK_NAME(geqp3)
#define ORGQR LM_MK_LAPACK_NAME(orgqr)
#define TRTRI LM_MK_LAPACK_NAME(trtri)
struct LMLEC_DATA{
LM_REAL *c, *Z, *p, *jac;
int ncnstr;
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata);
void (*jacf)(LM_REAL *p, LM_REAL *jac, int m, int n, void *adata);
void *adata;
};
/* prototypes for LAPACK routines */
#ifdef __cplusplus
extern "C" {
#endif
extern int GEQP3(int *m, int *n, LM_REAL *a, int *lda, int *jpvt,
LM_REAL *tau, LM_REAL *work, int *lwork, int *info);
extern int ORGQR(int *m, int *n, int *k, LM_REAL *a, int *lda, LM_REAL *tau,
LM_REAL *work, int *lwork, int *info);
extern int TRTRI(char *uplo, char *diag, int *n, LM_REAL *a, int *lda, int *info);
#ifdef __cplusplus
}
#endif
/*
* This function implements an elimination strategy for linearly constrained
* optimization problems. The strategy relies on QR decomposition to transform
* an optimization problem constrained by Ax=b to an equivalent, unconstrained
* one. Also referred to as "null space" or "reduced Hessian" method.
* See pp. 430-433 (chap. 15) of "Numerical Optimization" by Nocedal-Wright
* for details.
*
* A is mxn with m<=n and rank(A)=m
* Two matrices Y and Z of dimensions nxm and nx(n-m) are computed from A^T so that
* their columns are orthonormal and every x can be written as x=Y*b + Z*x_z=
* c + Z*x_z, where c=Y*b is a fixed vector of dimension n and x_z is an
* arbitrary vector of dimension n-m. Then, the problem of minimizing f(x)
* subject to Ax=b is equivalent to minimizing f(c + Z*x_z) with no constraints.
* The computed Y and Z are such that any solution of Ax=b can be written as
* x=Y*x_y + Z*x_z for some x_y, x_z. Furthermore, A*Y is nonsingular, A*Z=0
* and Z spans the null space of A.
*
* The function accepts A, b and computes c, Y, Z. If b or c is NULL, c is not
* computed. Also, Y can be NULL in which case it is not referenced.
* The function returns LM_ERROR in case of error, A's computed rank if successful
*
*/
static int LMLEC_ELIM(LM_REAL *A, LM_REAL *b, LM_REAL *c, LM_REAL *Y, LM_REAL *Z, int m, int n)
{
static LM_REAL eps=LM_CNST(-1.0);
LM_REAL *buf=NULL;
LM_REAL *a, *tau, *work, *r, aux;
register LM_REAL tmp;
int a_sz, jpvt_sz, tau_sz, r_sz, Y_sz, worksz;
int info, rank, *jpvt, tot_sz, mintmn, tm, tn;
register int i, j, k;
if(m>n){
fprintf(stderr, RCAT("matrix of constraints cannot have more rows than columns in", LMLEC_ELIM) "()!\n");
return LM_ERROR;
}
tm=n; tn=m; // transpose dimensions
mintmn=m;
/* calculate required memory size */
worksz=-1; // workspace query. Optimal work size is returned in aux
//ORGQR((int *)&tm, (int *)&tm, (int *)&mintmn, NULL, (int *)&tm, NULL, (LM_REAL *)&aux, &worksz, &info);
GEQP3((int *)&tm, (int *)&tn, NULL, (int *)&tm, NULL, NULL, (LM_REAL *)&aux, (int *)&worksz, &info);
worksz=(int)aux;
a_sz=tm*tm; // tm*tn is enough for xgeqp3()
jpvt_sz=tn;
tau_sz=mintmn;
r_sz=mintmn*mintmn; // actually smaller if a is not of full row rank
Y_sz=(Y)? 0 : tm*tn;
tot_sz=(a_sz + tau_sz + r_sz + worksz + Y_sz)*sizeof(LM_REAL) + jpvt_sz*sizeof(int); /* should be arranged in that order for proper doubles alignment */
buf=(LM_REAL *)malloc(tot_sz); /* allocate a "big" memory chunk at once */
if(!buf){
fprintf(stderr, RCAT("Memory allocation request failed in ", LMLEC_ELIM) "()\n");
return LM_ERROR;
}
a=buf;
tau=a+a_sz;
r=tau+tau_sz;
work=r+r_sz;
if(!Y){
Y=work+worksz;
jpvt=(int *)(Y+Y_sz);
}
else
jpvt=(int *)(work+worksz);
/* copy input array so that LAPACK won't destroy it. Note that copying is
* done in row-major order, which equals A^T in column-major
*/
for(i=0; i<tm*tn; ++i)
a[i]=A[i];
/* clear jpvt */
for(i=0; i<jpvt_sz; ++i) jpvt[i]=0;
/* rank revealing QR decomposition of A^T*/
GEQP3((int *)&tm, (int *)&tn, a, (int *)&tm, jpvt, tau, work, (int *)&worksz, &info);
//dgeqpf_((int *)&tm, (int *)&tn, a, (int *)&tm, jpvt, tau, work, &info);
/* error checking */
if(info!=0){
if(info<0){
fprintf(stderr, RCAT(RCAT("LAPACK error: illegal value for argument %d of ", GEQP3) " in ", LMLEC_ELIM) "()\n", -info);
}
else if(info>0){
fprintf(stderr, RCAT(RCAT("unknown LAPACK error (%d) for ", GEQP3) " in ", LMLEC_ELIM) "()\n", info);
}
free(buf);
return LM_ERROR;
}
/* the upper triangular part of a now contains the upper triangle of the unpermuted R */
if(eps<0.0){
LM_REAL aux;
/* compute machine epsilon. DBL_EPSILON should do also */
for(eps=LM_CNST(1.0); aux=eps+LM_CNST(1.0), aux-LM_CNST(1.0)>0.0; eps*=LM_CNST(0.5))
;
eps*=LM_CNST(2.0);
}
tmp=tm*LM_CNST(10.0)*eps*FABS(a[0]); // threshold. tm is max(tm, tn)
tmp=(tmp>LM_CNST(1E-12))? tmp : LM_CNST(1E-12); // ensure that threshold is not too small
/* compute A^T's numerical rank by counting the non-zeros in R's diagonal */
for(i=rank=0; i<mintmn; ++i)
if(a[i*(tm+1)]>tmp || a[i*(tm+1)]<-tmp) ++rank; /* loop across R's diagonal elements */
else break; /* diagonal is arranged in absolute decreasing order */
if(rank<tn){
fprintf(stderr, RCAT("\nConstraints matrix in ", LMLEC_ELIM) "() is not of full row rank (i.e. %d < %d)!\n"
"Make sure that you do not specify redundant or inconsistent constraints.\n\n", rank, tn);
free(buf);
return LM_ERROR;
}
/* compute the permuted inverse transpose of R */
/* first, copy R from the upper triangular part of a to the lower part of r (thus transposing it). R is rank x rank */
for(j=0; j<rank; ++j){
for(i=0; i<=j; ++i)
r[j+i*rank]=a[i+j*tm];
for(i=j+1; i<rank; ++i)
r[j+i*rank]=0.0; // upper part is zero
}
/* r now contains R^T */
/* compute the inverse */
TRTRI("L", "N", (int *)&rank, r, (int *)&rank, &info);
/* error checking */
if(info!=0){
if(info<0){
fprintf(stderr, RCAT(RCAT("LAPACK error: illegal value for argument %d of ", TRTRI) " in ", LMLEC_ELIM) "()\n", -info);
}
else if(info>0){
fprintf(stderr, RCAT(RCAT("A(%d, %d) is exactly zero for ", TRTRI) " (singular matrix) in ", LMLEC_ELIM) "()\n", info, info);
}
free(buf);
return LM_ERROR;
}
/* finally, permute R^-T using Y as intermediate storage */
for(j=0; j<rank; ++j)
for(i=0, k=jpvt[j]-1; i<rank; ++i)
Y[i+k*rank]=r[i+j*rank];
for(i=0; i<rank*rank; ++i) // copy back to r
r[i]=Y[i];
/* resize a to be tm x tm, filling with zeroes */
for(i=tm*tn; i<tm*tm; ++i)
a[i]=0.0;
/* compute Q in a as the product of elementary reflectors. Q is tm x tm */
ORGQR((int *)&tm, (int *)&tm, (int *)&mintmn, a, (int *)&tm, tau, work, &worksz, &info);
/* error checking */
if(info!=0){
if(info<0){
fprintf(stderr, RCAT(RCAT("LAPACK error: illegal value for argument %d of ", ORGQR) " in ", LMLEC_ELIM) "()\n", -info);
}
else if(info>0){
fprintf(stderr, RCAT(RCAT("unknown LAPACK error (%d) for ", ORGQR) " in ", LMLEC_ELIM) "()\n", info);
}
free(buf);
return LM_ERROR;
}
/* compute Y=Q_1*R^-T*P^T. Y is tm x rank */
for(i=0; i<tm; ++i)
for(j=0; j<rank; ++j){
for(k=0, tmp=0.0; k<rank; ++k)
tmp+=a[i+k*tm]*r[k+j*rank];
Y[i*rank+j]=tmp;
}
if(b && c){
/* compute c=Y*b */
for(i=0; i<tm; ++i){
for(j=0, tmp=0.0; j<rank; ++j)
tmp+=Y[i*rank+j]*b[j];
c[i]=tmp;
}
}
/* copy Q_2 into Z. Z is tm x (tm-rank) */
for(j=0; j<tm-rank; ++j)
for(i=0, k=j+rank; i<tm; ++i)
Z[i*(tm-rank)+j]=a[i+k*tm];
free(buf);
return rank;
}
/* constrained measurements: given pp, compute the measurements at c + Z*pp */
static void LMLEC_FUNC(LM_REAL *pp, LM_REAL *hx, int mm, int n, void *adata)
{
struct LMLEC_DATA *data=(struct LMLEC_DATA *)adata;
int m;
register int i, j;
register LM_REAL sum;
LM_REAL *c, *Z, *p, *Zimm;
m=mm+data->ncnstr;
c=data->c;
Z=data->Z;
p=data->p;
/* p=c + Z*pp */
for(i=0; i<m; ++i){
Zimm=Z+i*mm;
for(j=0, sum=c[i]; j<mm; ++j)
sum+=Zimm[j]*pp[j]; // sum+=Z[i*mm+j]*pp[j];
p[i]=sum;
}
(*(data->func))(p, hx, m, n, data->adata);
}
/* constrained Jacobian: given pp, compute the Jacobian at c + Z*pp
* Using the chain rule, the Jacobian with respect to pp equals the
* product of the Jacobian with respect to p (at c + Z*pp) times Z
*/
static void LMLEC_JACF(LM_REAL *pp, LM_REAL *jacjac, int mm, int n, void *adata)
{
struct LMLEC_DATA *data=(struct LMLEC_DATA *)adata;
int m;
register int i, j, l;
register LM_REAL sum, *aux1, *aux2;
LM_REAL *c, *Z, *p, *jac;
m=mm+data->ncnstr;
c=data->c;
Z=data->Z;
p=data->p;
jac=data->jac;
/* p=c + Z*pp */
for(i=0; i<m; ++i){
aux1=Z+i*mm;
for(j=0, sum=c[i]; j<mm; ++j)
sum+=aux1[j]*pp[j]; // sum+=Z[i*mm+j]*pp[j];
p[i]=sum;
}
(*(data->jacf))(p, jac, m, n, data->adata);
/* compute jac*Z in jacjac */
if(n*m<=__BLOCKSZ__SQ){ // this is a small problem
/* This is the straightforward way to compute jac*Z. However, due to
* its noncontinuous memory access pattern, it incures many cache misses when
* applied to large minimization problems (i.e. problems involving a large
* number of free variables and measurements), in which jac is too large to
* fit in the L1 cache. For such problems, a cache-efficient blocking scheme
* is preferable. On the other hand, the straightforward algorithm is faster
* on small problems since in this case it avoids the overheads of blocking.
*/
for(i=0; i<n; ++i){
aux1=jac+i*m;
aux2=jacjac+i*mm;
for(j=0; j<mm; ++j){
for(l=0, sum=0.0; l<m; ++l)
sum+=aux1[l]*Z[l*mm+j]; // sum+=jac[i*m+l]*Z[l*mm+j];
aux2[j]=sum; // jacjac[i*mm+j]=sum;
}
}
}
else{ // this is a large problem
/* Cache efficient computation of jac*Z based on blocking
*/
#define __MIN__(x, y) (((x)<=(y))? (x) : (y))
register int jj, ll;
for(jj=0; jj<mm; jj+=__BLOCKSZ__){
for(i=0; i<n; ++i){
aux1=jacjac+i*mm;
for(j=jj; j<__MIN__(jj+__BLOCKSZ__, mm); ++j)
aux1[j]=0.0; //jacjac[i*mm+j]=0.0;
}
for(ll=0; ll<m; ll+=__BLOCKSZ__){
for(i=0; i<n; ++i){
aux1=jacjac+i*mm; aux2=jac+i*m;
for(j=jj; j<__MIN__(jj+__BLOCKSZ__, mm); ++j){
sum=0.0;
for(l=ll; l<__MIN__(ll+__BLOCKSZ__, m); ++l)
sum+=aux2[l]*Z[l*mm+j]; //jac[i*m+l]*Z[l*mm+j];
aux1[j]+=sum; //jacjac[i*mm+j]+=sum;
}
}
}
}
}
}
#undef __MIN__
/*
* This function is similar to LEVMAR_DER except that the minimization
* is performed subject to the linear constraints A p=b, A is kxm, b kx1
*
* This function requires an analytic Jacobian. In case the latter is unavailable,
* use LEVMAR_LEC_DIF() bellow
*
*/
int LEVMAR_LEC_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata), /* function to evaluate the Jacobian \part x / \part p */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
LM_REAL *A, /* I: constraints matrix, kxm */
LM_REAL *b, /* I: right hand constraints vector, kx1 */
int k, /* I: number of constraints (i.e. A's #rows) */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[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_REAL info[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_LEC_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
*/
{
struct LMLEC_DATA data;
LM_REAL *ptr, *Z, *pp, *p0, *Zimm; /* Z is mxmm */
int mm, ret;
register int i, j;
register LM_REAL tmp;
LM_REAL locinfo[LM_INFO_SZ];
if(!jacf){
fprintf(stderr, RCAT("No function specified for computing the Jacobian in ", LEVMAR_LEC_DER)
RCAT("().\nIf no such function is available, use ", LEVMAR_LEC_DIF) RCAT("() rather than ", LEVMAR_LEC_DER) "()\n");
return LM_ERROR;
}
mm=m-k;
if(n<mm){
fprintf(stderr, LCAT(LEVMAR_LEC_DER, "(): cannot solve a problem with fewer measurements + equality constraints [%d + %d] than unknowns [%d]\n"), n, k, m);
return LM_ERROR;
}
ptr=(LM_REAL *)malloc((2*m + m*mm + n*m + mm)*sizeof(LM_REAL));
if(!ptr){
fprintf(stderr, LCAT(LEVMAR_LEC_DER, "(): memory allocation request failed\n"));
return LM_ERROR;
}
data.p=p;
p0=ptr;
data.c=p0+m;
data.Z=Z=data.c+m;
data.jac=data.Z+m*mm;
pp=data.jac+n*m;
data.ncnstr=k;
data.func=func;
data.jacf=jacf;
data.adata=adata;
ret=LMLEC_ELIM(A, b, data.c, NULL, Z, k, m); // compute c, Z
if(ret==LM_ERROR){
free(ptr);
return LM_ERROR;
}
/* compute pp s.t. p = c + Z*pp or (Z^T Z)*pp=Z^T*(p-c)
* Due to orthogonality, Z^T Z = I and the last equation
* becomes pp=Z^T*(p-c). Also, save the starting p in p0
*/
for(i=0; i<m; ++i){
p0[i]=p[i];
p[i]-=data.c[i];
}
/* Z^T*(p-c) */
for(i=0; i<mm; ++i){
for(j=0, tmp=0.0; j<m; ++j)
tmp+=Z[j*mm+i]*p[j];
pp[i]=tmp;
}
/* compute the p corresponding to pp (i.e. c + Z*pp) and compare with p0 */
for(i=0; i<m; ++i){
Zimm=Z+i*mm;
for(j=0, tmp=data.c[i]; j<mm; ++j)
tmp+=Zimm[j]*pp[j]; // tmp+=Z[i*mm+j]*pp[j];
if(FABS(tmp-p0[i])>LM_CNST(1E-03))
fprintf(stderr, RCAT("Warning: component %d of starting point not feasible in ", LEVMAR_LEC_DER) "()! [%.10g reset to %.10g]\n",
i, p0[i], tmp);
}
if(!info) info=locinfo; /* make sure that LEVMAR_DER() is called with non-null info */
/* note that covariance computation is not requested from LEVMAR_DER() */
ret=LEVMAR_DER(LMLEC_FUNC, LMLEC_JACF, pp, x, mm, n, itmax, opts, info, work, NULL, (void *)&data);
/* p=c + Z*pp */
for(i=0; i<m; ++i){
Zimm=Z+i*mm;
for(j=0, tmp=data.c[i]; j<mm; ++j)
tmp+=Zimm[j]*pp[j]; // tmp+=Z[i*mm+j]*pp[j];
p[i]=tmp;
}
/* compute the covariance from the Jacobian in data.jac */
if(covar){
LEVMAR_TRANS_MAT_MAT_MULT(data.jac, covar, n, m); /* covar = J^T J */
LEVMAR_COVAR(covar, covar, info[1], m, n);
}
free(ptr);
return ret;
}
/* Similar to the LEVMAR_LEC_DER() function above, except that the Jacobian is approximated
* with the aid of finite differences (forward or central, see the comment for the opts argument)
*/
int LEVMAR_LEC_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
LM_REAL *A, /* I: constraints matrix, kxm */
LM_REAL *b, /* I: right hand constraints vector, kx1 */
int k, /* I: number of constraints (i.e. A's #rows) */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[5], /* I: opts[0-3] = minim. options [\mu, \epsilon1, \epsilon2, \epsilon3, \delta]. Respectively the
* 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_REAL info[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_LEC_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
*/
{
struct LMLEC_DATA data;
LM_REAL *ptr, *Z, *pp, *p0, *Zimm; /* Z is mxmm */
int mm, ret;
register int i, j;
register LM_REAL tmp;
LM_REAL locinfo[LM_INFO_SZ];
mm=m-k;
if(n<mm){
fprintf(stderr, LCAT(LEVMAR_LEC_DIF, "(): cannot solve a problem with fewer measurements + equality constraints [%d + %d] than unknowns [%d]\n"), n, k, m);
return LM_ERROR;
}
ptr=(LM_REAL *)malloc((2*m + m*mm + mm)*sizeof(LM_REAL));
if(!ptr){
fprintf(stderr, LCAT(LEVMAR_LEC_DIF, "(): memory allocation request failed\n"));
return LM_ERROR;
}
data.p=p;
p0=ptr;
data.c=p0+m;
data.Z=Z=data.c+m;
data.jac=NULL;
pp=data.Z+m*mm;
data.ncnstr=k;
data.func=func;
data.jacf=NULL;
data.adata=adata;
ret=LMLEC_ELIM(A, b, data.c, NULL, Z, k, m); // compute c, Z
if(ret==LM_ERROR){
free(ptr);
return LM_ERROR;
}
/* compute pp s.t. p = c + Z*pp or (Z^T Z)*pp=Z^T*(p-c)
* Due to orthogonality, Z^T Z = I and the last equation
* becomes pp=Z^T*(p-c). Also, save the starting p in p0
*/
for(i=0; i<m; ++i){
p0[i]=p[i];
p[i]-=data.c[i];
}
/* Z^T*(p-c) */
for(i=0; i<mm; ++i){
for(j=0, tmp=0.0; j<m; ++j)
tmp+=Z[j*mm+i]*p[j];
pp[i]=tmp;
}
/* compute the p corresponding to pp (i.e. c + Z*pp) and compare with p0 */
for(i=0; i<m; ++i){
Zimm=Z+i*mm;
for(j=0, tmp=data.c[i]; j<mm; ++j)
tmp+=Zimm[j]*pp[j]; // tmp+=Z[i*mm+j]*pp[j];
if(FABS(tmp-p0[i])>LM_CNST(1E-03))
fprintf(stderr, RCAT("Warning: component %d of starting point not feasible in ", LEVMAR_LEC_DIF) "()! [%.10g reset to %.10g]\n",
i, p0[i], tmp);
}
if(!info) info=locinfo; /* make sure that LEVMAR_DIF() is called with non-null info */
/* note that covariance computation is not requested from LEVMAR_DIF() */
ret=LEVMAR_DIF(LMLEC_FUNC, pp, x, mm, n, itmax, opts, info, work, NULL, (void *)&data);
/* p=c + Z*pp */
for(i=0; i<m; ++i){
Zimm=Z+i*mm;
for(j=0, tmp=data.c[i]; j<mm; ++j)
tmp+=Zimm[j]*pp[j]; // tmp+=Z[i*mm+j]*pp[j];
p[i]=tmp;
}
/* compute the Jacobian with finite differences and use it to estimate the covariance */
if(covar){
LM_REAL *hx, *wrk, *jac;
hx=(LM_REAL *)malloc((2*n+n*m)*sizeof(LM_REAL));
if(!hx){
fprintf(stderr, LCAT(LEVMAR_LEC_DIF, "(): memory allocation request failed\n"));
free(ptr);
return LM_ERROR;
}
wrk=hx+n;
jac=wrk+n;
(*func)(p, hx, m, n, adata); /* evaluate function at p */
LEVMAR_FDIF_FORW_JAC_APPROX(func, p, hx, wrk, (LM_REAL)LM_DIFF_DELTA, jac, m, n, adata); /* compute the Jacobian at p */
LEVMAR_TRANS_MAT_MAT_MULT(jac, covar, n, m); /* covar = J^T J */
LEVMAR_COVAR(covar, covar, info[1], m, n);
free(hx);
}
free(ptr);
return ret;
}
/* undefine all. THIS MUST REMAIN AT THE END OF THE FILE */
#undef LMLEC_DATA
#undef LMLEC_ELIM
#undef LMLEC_FUNC
#undef LMLEC_JACF
#undef LEVMAR_FDIF_FORW_JAC_APPROX
#undef LEVMAR_COVAR
#undef LEVMAR_TRANS_MAT_MAT_MULT
#undef LEVMAR_LEC_DER
#undef LEVMAR_LEC_DIF
#undef LEVMAR_DER
#undef LEVMAR_DIF
#undef GEQP3
#undef ORGQR
#undef TRTRI

70
levmar/misc.c Normal file
View File

@@ -0,0 +1,70 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-05 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/********************************************************************************
* Miscelaneous functions for Levenberg-Marquardt nonlinear minimization. The
* same core code is used with appropriate #defines to derive single and double
* precision versions, see also misc_core.c
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "levmar.h"
#include "misc.h"
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define LM_REAL_EPSILON FLT_EPSILON
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#include "misc_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_EPSILON
#undef __SUBCNST
#undef LM_CNST
#endif /* LM_SNGL_PREC */
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_REAL_EPSILON DBL_EPSILON
#define LM_CNST(x) (x)
#include "misc_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_EPSILON
#undef LM_CNST
#endif /* LM_DBL_PREC */

114
levmar/misc.h Normal file
View File

@@ -0,0 +1,114 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef _MISC_H_
#define _MISC_H_
/* common suffix for LAPACK subroutines. Define empty in case of no prefix. */
#define LM_LAPACK_SUFFIX _
//#define LM_LAPACK_SUFFIX // define empty
/* common prefix for BLAS subroutines. Leave undefined in case of no prefix.
* You might also need to modify LM_BLAS_PREFIX below
*/
/* f2c'd BLAS */
//#define LM_BLAS_PREFIX f2c_
/* C BLAS */
//#define LM_BLAS_PREFIX cblas_
/* common suffix for BLAS subroutines */
//#define LM_BLAS_SUFFIX // define empty if a f2c_ or cblas_ prefix was defined for LM_BLAS_PREFIX above
#define LM_BLAS_SUFFIX _ // use this in case of no BLAS prefix
#define LCAT_(a, b) #a b
#define LCAT(a, b) LCAT_(a, b) // force substitution
#define RCAT_(a, b) a #b
#define RCAT(a, b) RCAT_(a, b) // force substitution
#define LM_MK_LAPACK_NAME(s) LM_ADD_PREFIX(LM_CAT_(s, LM_LAPACK_SUFFIX))
#ifdef LM_BLAS_PREFIX
#define LM_MK_BLAS_NAME(s) LM_CAT_(LM_BLAS_PREFIX, LM_ADD_PREFIX(LM_CAT_(s, LM_BLAS_SUFFIX)))
#else
#define LM_MK_BLAS_NAME(s) LM_ADD_PREFIX(LM_CAT_(s, LM_BLAS_SUFFIX))
#endif
#define __BLOCKSZ__ 32 /* block size for cache-friendly matrix-matrix multiply. It should be
* such that __BLOCKSZ__^2*sizeof(LM_REAL) is smaller than the CPU (L1)
* data cache size. Notice that a value of 32 when LM_REAL=double assumes
* an 8Kb L1 data cache (32*32*8=8K). This is a concervative choice since
* newer Pentium 4s have a L1 data cache of size 16K, capable of holding
* up to 45x45 double blocks.
*/
#define __BLOCKSZ__SQ (__BLOCKSZ__)*(__BLOCKSZ__)
/* add a prefix in front of a token */
#define LM_CAT__(a, b) a ## b
#define LM_CAT_(a, b) LM_CAT__(a, b) // force substitution
#define LM_ADD_PREFIX(s) LM_CAT_(LM_PREFIX, s)
#define FABS(x) (((x)>=0.0)? (x) : -(x))
#ifdef __cplusplus
extern "C" {
#endif
/* blocking-based matrix multiply */
extern void slevmar_trans_mat_mat_mult(float *a, float *b, int n, int m);
extern void dlevmar_trans_mat_mat_mult(double *a, double *b, int n, int m);
/* forward finite differences */
extern void slevmar_fdif_forw_jac_approx(void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *hx, float *hxx, float delta,
float *jac, int m, int n, void *adata);
extern void dlevmar_fdif_forw_jac_approx(void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *hx, double *hxx, double delta,
double *jac, int m, int n, void *adata);
/* central finite differences */
extern void slevmar_fdif_cent_jac_approx(void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *hxm, float *hxp, float delta,
float *jac, int m, int n, void *adata);
extern void dlevmar_fdif_cent_jac_approx(void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *hxm, double *hxp, double delta,
double *jac, int m, int n, void *adata);
/* e=x-y and ||e|| */
extern float slevmar_L2nrmxmy(float *e, float *x, float *y, int n);
extern double dlevmar_L2nrmxmy(double *e, double *x, double *y, int n);
/* covariance of LS fit */
extern int slevmar_covar(float *JtJ, float *C, float sumsq, int m, int n);
extern int dlevmar_covar(double *JtJ, double *C, double sumsq, int m, int n);
/* box constraints consistency check */
extern int slevmar_box_check(float *lb, float *ub, int m);
extern int dlevmar_box_check(double *lb, double *ub, int m);
/* Cholesky */
extern int slevmar_chol(float *C, float *W, int m);
extern int dlevmar_chol(double *C, double *W, int m);
#ifdef __cplusplus
}
#endif
#endif /* _MISC_H_ */

826
levmar/misc_core.c Normal file
View File

@@ -0,0 +1,826 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-05 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef LM_REAL // not included by misc.c
#error This file should not be compiled directly!
#endif
/* precision-specific definitions */
#define LEVMAR_CHKJAC LM_ADD_PREFIX(levmar_chkjac)
#define LEVMAR_FDIF_FORW_JAC_APPROX LM_ADD_PREFIX(levmar_fdif_forw_jac_approx)
#define LEVMAR_FDIF_CENT_JAC_APPROX LM_ADD_PREFIX(levmar_fdif_cent_jac_approx)
#define LEVMAR_TRANS_MAT_MAT_MULT LM_ADD_PREFIX(levmar_trans_mat_mat_mult)
#define LEVMAR_COVAR LM_ADD_PREFIX(levmar_covar)
#define LEVMAR_STDDEV LM_ADD_PREFIX(levmar_stddev)
#define LEVMAR_CORCOEF LM_ADD_PREFIX(levmar_corcoef)
#define LEVMAR_R2 LM_ADD_PREFIX(levmar_R2)
#define LEVMAR_BOX_CHECK LM_ADD_PREFIX(levmar_box_check)
#define LEVMAR_L2NRMXMY LM_ADD_PREFIX(levmar_L2nrmxmy)
#ifdef HAVE_LAPACK
#define LEVMAR_PSEUDOINVERSE LM_ADD_PREFIX(levmar_pseudoinverse)
static int LEVMAR_PSEUDOINVERSE(LM_REAL *A, LM_REAL *B, int m);
#ifdef __cplusplus
extern "C" {
#endif
/* BLAS matrix multiplication, LAPACK SVD & Cholesky routines */
#define GEMM LM_MK_BLAS_NAME(gemm)
/* C := alpha*op( A )*op( B ) + beta*C */
extern void GEMM(char *transa, char *transb, int *m, int *n, int *k,
LM_REAL *alpha, LM_REAL *a, int *lda, LM_REAL *b, int *ldb, LM_REAL *beta, LM_REAL *c, int *ldc);
#define GESVD LM_MK_LAPACK_NAME(gesvd)
#define GESDD LM_MK_LAPACK_NAME(gesdd)
extern int GESVD(char *jobu, char *jobvt, int *m, int *n, LM_REAL *a, int *lda, LM_REAL *s, LM_REAL *u, int *ldu,
LM_REAL *vt, int *ldvt, LM_REAL *work, int *lwork, int *info);
/* lapack 3.0 new SVD routine, faster than xgesvd() */
extern int GESDD(char *jobz, int *m, int *n, LM_REAL *a, int *lda, LM_REAL *s, LM_REAL *u, int *ldu, LM_REAL *vt, int *ldvt,
LM_REAL *work, int *lwork, int *iwork, int *info);
/* Cholesky decomposition */
#define POTF2 LM_MK_LAPACK_NAME(potf2)
extern int POTF2(char *uplo, int *n, LM_REAL *a, int *lda, int *info);
#ifdef __cplusplus
}
#endif
#define LEVMAR_CHOLESKY LM_ADD_PREFIX(levmar_chol)
#else /* !HAVE_LAPACK */
#define LEVMAR_LUINVERSE LM_ADD_PREFIX(levmar_LUinverse_noLapack)
static int LEVMAR_LUINVERSE(LM_REAL *A, LM_REAL *B, int m);
#endif /* HAVE_LAPACK */
/* blocked multiplication of the transpose of the nxm matrix a with itself (i.e. a^T a)
* using a block size of bsize. The product is returned in b.
* Since a^T a is symmetric, its computation can be sped up by computing only its
* upper triangular part and copying it to the lower part.
*
* More details on blocking can be found at
* http://www-2.cs.cmu.edu/afs/cs/academic/class/15213-f02/www/R07/section_a/Recitation07-SectionA.pdf
*/
void LEVMAR_TRANS_MAT_MAT_MULT(LM_REAL *a, LM_REAL *b, int n, int m)
{
#ifdef HAVE_LAPACK /* use BLAS matrix multiply */
LM_REAL alpha=LM_CNST(1.0), beta=LM_CNST(0.0);
/* Fool BLAS to compute a^T*a avoiding transposing a: a is equivalent to a^T in column major,
* therefore BLAS computes a*a^T with a and a*a^T in column major, which is equivalent to
* computing a^T*a in row major!
*/
GEMM("N", "T", &m, &m, &n, &alpha, a, &m, a, &m, &beta, b, &m);
#else /* no LAPACK, use blocking-based multiply */
register int i, j, k, jj, kk;
register LM_REAL sum, *bim, *akm;
const int bsize=__BLOCKSZ__;
#define __MIN__(x, y) (((x)<=(y))? (x) : (y))
#define __MAX__(x, y) (((x)>=(y))? (x) : (y))
/* compute upper triangular part using blocking */
for(jj=0; jj<m; jj+=bsize){
for(i=0; i<m; ++i){
bim=b+i*m;
for(j=__MAX__(jj, i); j<__MIN__(jj+bsize, m); ++j)
bim[j]=0.0; //b[i*m+j]=0.0;
}
for(kk=0; kk<n; kk+=bsize){
for(i=0; i<m; ++i){
bim=b+i*m;
for(j=__MAX__(jj, i); j<__MIN__(jj+bsize, m); ++j){
sum=0.0;
for(k=kk; k<__MIN__(kk+bsize, n); ++k){
akm=a+k*m;
sum+=akm[i]*akm[j]; //a[k*m+i]*a[k*m+j];
}
bim[j]+=sum; //b[i*m+j]+=sum;
}
}
}
}
/* copy upper triangular part to the lower one */
for(i=0; i<m; ++i)
for(j=0; j<i; ++j)
b[i*m+j]=b[j*m+i];
#undef __MIN__
#undef __MAX__
#endif /* HAVE_LAPACK */
}
/* forward finite difference approximation to the Jacobian of func */
void LEVMAR_FDIF_FORW_JAC_APPROX(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
/* function to differentiate */
LM_REAL *p, /* I: current parameter estimate, mx1 */
LM_REAL *hx, /* I: func evaluated at p, i.e. hx=func(p), nx1 */
LM_REAL *hxx, /* W/O: work array for evaluating func(p+delta), nx1 */
LM_REAL delta, /* increment for computing the Jacobian */
LM_REAL *jac, /* O: array for storing approximated Jacobian, nxm */
int m,
int n,
void *adata)
{
register int i, j;
LM_REAL tmp;
register LM_REAL d;
for(j=0; j<m; ++j){
/* determine d=max(1E-04*|p[j]|, delta), see HZ */
d=LM_CNST(1E-04)*p[j]; // force evaluation
d=FABS(d);
if(d<delta)
d=delta;
tmp=p[j];
p[j]+=d;
(*func)(p, hxx, m, n, adata);
p[j]=tmp; /* restore */
d=LM_CNST(1.0)/d; /* invert so that divisions can be carried out faster as multiplications */
for(i=0; i<n; ++i){
jac[i*m+j]=(hxx[i]-hx[i])*d;
}
}
}
/* central finite difference approximation to the Jacobian of func */
void LEVMAR_FDIF_CENT_JAC_APPROX(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
/* function to differentiate */
LM_REAL *p, /* I: current parameter estimate, mx1 */
LM_REAL *hxm, /* W/O: work array for evaluating func(p-delta), nx1 */
LM_REAL *hxp, /* W/O: work array for evaluating func(p+delta), nx1 */
LM_REAL delta, /* increment for computing the Jacobian */
LM_REAL *jac, /* O: array for storing approximated Jacobian, nxm */
int m,
int n,
void *adata)
{
register int i, j;
LM_REAL tmp;
register LM_REAL d;
for(j=0; j<m; ++j){
/* determine d=max(1E-04*|p[j]|, delta), see HZ */
d=LM_CNST(1E-04)*p[j]; // force evaluation
d=FABS(d);
if(d<delta)
d=delta;
tmp=p[j];
p[j]-=d;
(*func)(p, hxm, m, n, adata);
p[j]=tmp+d;
(*func)(p, hxp, m, n, adata);
p[j]=tmp; /* restore */
d=LM_CNST(0.5)/d; /* invert so that divisions can be carried out faster as multiplications */
for(i=0; i<n; ++i){
jac[i*m+j]=(hxp[i]-hxm[i])*d;
}
}
}
/*
* Check the Jacobian of a n-valued nonlinear function in m variables
* evaluated at a point p, for consistency with the function itself.
*
* Based on fortran77 subroutine CHKDER by
* Burton S. Garbow, Kenneth E. Hillstrom, Jorge J. More
* Argonne National Laboratory. MINPACK project. March 1980.
*
*
* func points to a function from R^m --> R^n: Given a p in R^m it yields hx in R^n
* jacf points to a function implementing the Jacobian of func, whose correctness
* is to be tested. Given a p in R^m, jacf computes into the nxm matrix j the
* Jacobian of func at p. Note that row i of j corresponds to the gradient of
* the i-th component of func, evaluated at p.
* p is an input array of length m containing the point of evaluation.
* m is the number of variables
* n is the number of functions
* adata points to possible additional data and is passed uninterpreted
* to func, jacf.
* err is an array of length n. On output, err contains measures
* of correctness of the respective gradients. if there is
* no severe loss of significance, then if err[i] is 1.0 the
* i-th gradient is correct, while if err[i] is 0.0 the i-th
* gradient is incorrect. For values of err between 0.0 and 1.0,
* the categorization is less certain. In general, a value of
* err[i] greater than 0.5 indicates that the i-th gradient is
* probably correct, while a value of err[i] less than 0.5
* indicates that the i-th gradient is probably incorrect.
*
*
* The function does not perform reliably if cancellation or
* rounding errors cause a severe loss of significance in the
* evaluation of a function. therefore, none of the components
* of p should be unusually small (in particular, zero) or any
* other value which may cause loss of significance.
*/
void LEVMAR_CHKJAC(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata),
LM_REAL *p, int m, int n, void *adata, LM_REAL *err)
{
LM_REAL factor=LM_CNST(100.0);
LM_REAL one=LM_CNST(1.0);
LM_REAL zero=LM_CNST(0.0);
LM_REAL *fvec, *fjac, *pp, *fvecp, *buf;
register int i, j;
LM_REAL eps, epsf, temp, epsmch;
LM_REAL epslog;
int fvec_sz=n, fjac_sz=n*m, pp_sz=m, fvecp_sz=n;
epsmch=LM_REAL_EPSILON;
eps=(LM_REAL)sqrt(epsmch);
buf=(LM_REAL *)malloc((fvec_sz + fjac_sz + pp_sz + fvecp_sz)*sizeof(LM_REAL));
if(!buf){
fprintf(stderr, LCAT(LEVMAR_CHKJAC, "(): memory allocation request failed\n"));
exit(1);
}
fvec=buf;
fjac=fvec+fvec_sz;
pp=fjac+fjac_sz;
fvecp=pp+pp_sz;
/* compute fvec=func(p) */
(*func)(p, fvec, m, n, adata);
/* compute the Jacobian at p */
(*jacf)(p, fjac, m, n, adata);
/* compute pp */
for(j=0; j<m; ++j){
temp=eps*FABS(p[j]);
if(temp==zero) temp=eps;
pp[j]=p[j]+temp;
}
/* compute fvecp=func(pp) */
(*func)(pp, fvecp, m, n, adata);
epsf=factor*epsmch;
epslog=(LM_REAL)log10(eps);
for(i=0; i<n; ++i)
err[i]=zero;
for(j=0; j<m; ++j){
temp=FABS(p[j]);
if(temp==zero) temp=one;
for(i=0; i<n; ++i)
err[i]+=temp*fjac[i*m+j];
}
for(i=0; i<n; ++i){
temp=one;
if(fvec[i]!=zero && fvecp[i]!=zero && FABS(fvecp[i]-fvec[i])>=epsf*FABS(fvec[i]))
temp=eps*FABS((fvecp[i]-fvec[i])/eps - err[i])/(FABS(fvec[i])+FABS(fvecp[i]));
err[i]=one;
if(temp>epsmch && temp<eps)
err[i]=((LM_REAL)log10(temp) - epslog)/epslog;
if(temp>=eps) err[i]=zero;
}
free(buf);
return;
}
#ifdef HAVE_LAPACK
/*
* This function computes the pseudoinverse of a square matrix A
* into B using SVD. A and B can coincide
*
* The function returns 0 in case of error (e.g. A is singular),
* the rank of A if successful
*
* A, B are mxm
*
*/
static int LEVMAR_PSEUDOINVERSE(LM_REAL *A, LM_REAL *B, int m)
{
LM_REAL *buf=NULL;
int buf_sz=0;
static LM_REAL eps=LM_CNST(-1.0);
register int i, j;
LM_REAL *a, *u, *s, *vt, *work;
int a_sz, u_sz, s_sz, vt_sz, tot_sz;
LM_REAL thresh, one_over_denom;
int info, rank, worksz, *iwork, iworksz;
/* calculate required memory size */
worksz=5*m; // min worksize for GESVD
//worksz=m*(7*m+4); // min worksize for GESDD
iworksz=8*m;
a_sz=m*m;
u_sz=m*m; s_sz=m; vt_sz=m*m;
tot_sz=(a_sz + u_sz + s_sz + vt_sz + worksz)*sizeof(LM_REAL) + iworksz*sizeof(int); /* should be arranged in that order for proper doubles alignment */
buf_sz=tot_sz;
buf=(LM_REAL *)malloc(buf_sz);
if(!buf){
fprintf(stderr, RCAT("memory allocation in ", LEVMAR_PSEUDOINVERSE) "() failed!\n");
return 0; /* error */
}
a=buf;
u=a+a_sz;
s=u+u_sz;
vt=s+s_sz;
work=vt+vt_sz;
iwork=(int *)(work+worksz);
/* store A (column major!) into a */
for(i=0; i<m; i++)
for(j=0; j<m; j++)
a[i+j*m]=A[i*m+j];
/* SVD decomposition of A */
GESVD("A", "A", (int *)&m, (int *)&m, a, (int *)&m, s, u, (int *)&m, vt, (int *)&m, work, (int *)&worksz, &info);
//GESDD("A", (int *)&m, (int *)&m, a, (int *)&m, s, u, (int *)&m, vt, (int *)&m, work, (int *)&worksz, iwork, &info);
/* error treatment */
if(info!=0){
if(info<0){
fprintf(stderr, RCAT(RCAT(RCAT("LAPACK error: illegal value for argument %d of ", GESVD), "/" GESDD) " in ", LEVMAR_PSEUDOINVERSE) "()\n", -info);
}
else{
fprintf(stderr, RCAT("LAPACK error: dgesdd (dbdsdc)/dgesvd (dbdsqr) failed to converge in ", LEVMAR_PSEUDOINVERSE) "() [info=%d]\n", info);
}
free(buf);
return 0;
}
if(eps<0.0){
LM_REAL aux;
/* compute machine epsilon */
for(eps=LM_CNST(1.0); aux=eps+LM_CNST(1.0), aux-LM_CNST(1.0)>0.0; eps*=LM_CNST(0.5))
;
eps*=LM_CNST(2.0);
}
/* compute the pseudoinverse in B */
for(i=0; i<a_sz; i++) B[i]=0.0; /* initialize to zero */
for(rank=0, thresh=eps*s[0]; rank<m && s[rank]>thresh; rank++){
one_over_denom=LM_CNST(1.0)/s[rank];
for(j=0; j<m; j++)
for(i=0; i<m; i++)
B[i*m+j]+=vt[rank+i*m]*u[j+rank*m]*one_over_denom;
}
free(buf);
return rank;
}
#else // no LAPACK
/*
* This function computes the inverse of A in B. A and B can coincide
*
* The function employs LAPACK-free LU decomposition of A to solve m linear
* systems A*B_i=I_i, where B_i and I_i are the i-th columns of B and I.
*
* A and B are mxm
*
* The function returns 0 in case of error, 1 if successful
*
*/
static int LEVMAR_LUINVERSE(LM_REAL *A, LM_REAL *B, int m)
{
void *buf=NULL;
int buf_sz=0;
register int i, j, k, l;
int *idx, maxi=-1, idx_sz, a_sz, x_sz, work_sz, tot_sz;
LM_REAL *a, *x, *work, max, sum, tmp;
/* calculate required memory size */
idx_sz=m;
a_sz=m*m;
x_sz=m;
work_sz=m;
tot_sz=(a_sz + x_sz + work_sz)*sizeof(LM_REAL) + idx_sz*sizeof(int); /* should be arranged in that order for proper doubles alignment */
buf_sz=tot_sz;
buf=(void *)malloc(tot_sz);
if(!buf){
fprintf(stderr, RCAT("memory allocation in ", LEVMAR_LUINVERSE) "() failed!\n");
return 0; /* error */
}
a=buf;
x=a+a_sz;
work=x+x_sz;
idx=(int *)(work+work_sz);
/* avoid destroying A by copying it to a */
for(i=0; i<a_sz; ++i) a[i]=A[i];
/* compute the LU decomposition of a row permutation of matrix a; the permutation itself is saved in idx[] */
for(i=0; i<m; ++i){
max=0.0;
for(j=0; j<m; ++j)
if((tmp=FABS(a[i*m+j]))>max)
max=tmp;
if(max==0.0){
fprintf(stderr, RCAT("Singular matrix A in ", LEVMAR_LUINVERSE) "()!\n");
free(buf);
return 0;
}
work[i]=LM_CNST(1.0)/max;
}
for(j=0; j<m; ++j){
for(i=0; i<j; ++i){
sum=a[i*m+j];
for(k=0; k<i; ++k)
sum-=a[i*m+k]*a[k*m+j];
a[i*m+j]=sum;
}
max=0.0;
for(i=j; i<m; ++i){
sum=a[i*m+j];
for(k=0; k<j; ++k)
sum-=a[i*m+k]*a[k*m+j];
a[i*m+j]=sum;
if((tmp=work[i]*FABS(sum))>=max){
max=tmp;
maxi=i;
}
}
if(j!=maxi){
for(k=0; k<m; ++k){
tmp=a[maxi*m+k];
a[maxi*m+k]=a[j*m+k];
a[j*m+k]=tmp;
}
work[maxi]=work[j];
}
idx[j]=maxi;
if(a[j*m+j]==0.0)
a[j*m+j]=LM_REAL_EPSILON;
if(j!=m-1){
tmp=LM_CNST(1.0)/(a[j*m+j]);
for(i=j+1; i<m; ++i)
a[i*m+j]*=tmp;
}
}
/* The decomposition has now replaced a. Solve the m linear systems using
* forward and back substitution
*/
for(l=0; l<m; ++l){
for(i=0; i<m; ++i) x[i]=0.0;
x[l]=LM_CNST(1.0);
for(i=k=0; i<m; ++i){
j=idx[i];
sum=x[j];
x[j]=x[i];
if(k!=0)
for(j=k-1; j<i; ++j)
sum-=a[i*m+j]*x[j];
else
if(sum!=0.0)
k=i+1;
x[i]=sum;
}
for(i=m-1; i>=0; --i){
sum=x[i];
for(j=i+1; j<m; ++j)
sum-=a[i*m+j]*x[j];
x[i]=sum/a[i*m+i];
}
for(i=0; i<m; ++i)
B[i*m+l]=x[i];
}
free(buf);
return 1;
}
#endif /* HAVE_LAPACK */
/*
* This function computes in C the covariance matrix corresponding to a least
* squares fit. JtJ is the approximate Hessian at the solution (i.e. J^T*J, where
* J is the Jacobian at the solution), sumsq is the sum of squared residuals
* (i.e. goodnes of fit) at the solution, m is the number of parameters (variables)
* and n the number of observations. JtJ can coincide with C.
*
* if JtJ is of full rank, C is computed as sumsq/(n-m)*(JtJ)^-1
* otherwise and if LAPACK is available, C=sumsq/(n-r)*(JtJ)^+
* where r is JtJ's rank and ^+ denotes the pseudoinverse
* The diagonal of C is made up from the estimates of the variances
* of the estimated regression coefficients.
* See the documentation of routine E04YCF from the NAG fortran lib
*
* The function returns the rank of JtJ if successful, 0 on error
*
* A and C are mxm
*
*/
int LEVMAR_COVAR(LM_REAL *JtJ, LM_REAL *C, LM_REAL sumsq, int m, int n)
{
register int i;
int rnk;
LM_REAL fact;
#ifdef HAVE_LAPACK
rnk=LEVMAR_PSEUDOINVERSE(JtJ, C, m);
if(!rnk) return 0;
#else
#ifdef _MSC_VER
#pragma message("LAPACK not available, LU will be used for matrix inversion when computing the covariance; this might be unstable at times")
#else
#warning LAPACK not available, LU will be used for matrix inversion when computing the covariance; this might be unstable at times
#endif // _MSC_VER
rnk=LEVMAR_LUINVERSE(JtJ, C, m);
if(!rnk) return 0;
rnk=m; /* assume full rank */
#endif /* HAVE_LAPACK */
fact=sumsq/(LM_REAL)(n-rnk);
for(i=0; i<m*m; ++i)
C[i]*=fact;
return rnk;
}
/* standard deviation of the best-fit parameter i.
* covar is the mxm covariance matrix of the best-fit parameters (see also LEVMAR_COVAR()).
*
* The standard deviation is computed as \sigma_{i} = \sqrt{C_{ii}}
*/
LM_REAL LEVMAR_STDDEV(LM_REAL *covar, int m, int i)
{
return (LM_REAL)sqrt(covar[i*m+i]);
}
/* Pearson's correlation coefficient of the best-fit parameters i and j.
* covar is the mxm covariance matrix of the best-fit parameters (see also LEVMAR_COVAR()).
*
* The coefficient is computed as \rho_{ij} = C_{ij} / sqrt(C_{ii} C_{jj})
*/
LM_REAL LEVMAR_CORCOEF(LM_REAL *covar, int m, int i, int j)
{
return (LM_REAL)(covar[i*m+j]/sqrt(covar[i*m+i]*covar[j*m+j]));
}
/* coefficient of determination.
* see http://en.wikipedia.org/wiki/Coefficient_of_determination
*/
LM_REAL LEVMAR_R2(void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n, void *adata)
{
register int i;
register LM_REAL tmp;
LM_REAL SSerr, // sum of squared errors, i.e. residual sum of squares \sum_i (x_i-hx_i)^2
SStot, // \sum_i (x_i-xavg)^2
*hx, xavg;
if((hx=(LM_REAL *)malloc(n*sizeof(LM_REAL)))==NULL){
fprintf(stderr, RCAT("memory allocation request failed in ", LEVMAR_R2) "()\n");
exit(1);
}
/* hx=f(p) */
(*func)(p, hx, m, n, adata);
for(i=n, tmp=0.0; i-->0; )
tmp+=x[i];
xavg=tmp/(LM_REAL)n;
if(x)
for(i=n, SSerr=SStot=0.0; i-->0; ){
tmp=x[i]-hx[i];
SSerr+=tmp*tmp;
tmp=x[i]-xavg;
SStot+=tmp*tmp;
}
else /* x==0 */
for(i=n, SSerr=SStot=0.0; i-->0; ){
tmp=-hx[i];
SSerr+=tmp*tmp;
tmp=-xavg;
SStot+=tmp*tmp;
}
free(hx);
return LM_CNST(1.0) - SSerr/SStot;
}
/* check box constraints for consistency */
int LEVMAR_BOX_CHECK(LM_REAL *lb, LM_REAL *ub, int m)
{
register int i;
if(!lb || !ub) return 1;
for(i=0; i<m; ++i)
if(lb[i]>ub[i]) return 0;
return 1;
}
#ifdef HAVE_LAPACK
/* compute the Cholesky decomposition of C in W, s.t. C=W^t W and W is upper triangular */
int LEVMAR_CHOLESKY(LM_REAL *C, LM_REAL *W, int m)
{
register int i, j;
int info;
/* copy weights array C to W so that LAPACK won't destroy it;
* C is assumed symmetric, hence no transposition is needed
*/
for(i=0, j=m*m; i<j; ++i)
W[i]=C[i];
/* Cholesky decomposition */
POTF2("L", (int *)&m, W, (int *)&m, (int *)&info);
/* error treatment */
if(info!=0){
if(info<0){
fprintf(stderr, "LAPACK error: illegal value for argument %d of dpotf2 in %s\n", -info, LCAT(LEVMAR_CHOLESKY, "()"));
}
else{
fprintf(stderr, "LAPACK error: the leading minor of order %d is not positive definite,\n%s()\n", info,
RCAT("and the Cholesky factorization could not be completed in ", LEVMAR_CHOLESKY));
}
return LM_ERROR;
}
/* the decomposition is in the lower part of W (in column-major order!).
* zeroing the upper part makes it lower triangular which is equivalent to
* upper triangular in row-major order
*/
for(i=0; i<m; i++)
for(j=i+1; j<m; j++)
W[i+j*m]=0.0;
return 0;
}
#endif /* HAVE_LAPACK */
/* Compute e=x-y for two n-vectors x and y and return the squared L2 norm of e.
* e can coincide with either x or y; x can be NULL, in which case it is assumed
* to be equal to the zero vector.
* Uses loop unrolling and blocking to reduce bookkeeping overhead & pipeline
* stalls and increase instruction-level parallelism; see http://www.abarnett.demon.co.uk/tutorial.html
*/
LM_REAL LEVMAR_L2NRMXMY(LM_REAL *e, LM_REAL *x, LM_REAL *y, int n)
{
const int blocksize=8, bpwr=3; /* 8=2^3 */
register int i;
int j1, j2, j3, j4, j5, j6, j7;
int blockn;
register LM_REAL sum0=0.0, sum1=0.0, sum2=0.0, sum3=0.0;
/* n may not be divisible by blocksize,
* go as near as we can first, then tidy up.
*/
blockn = (n>>bpwr)<<bpwr; /* (n / blocksize) * blocksize; */
/* unroll the loop in blocks of `blocksize'; looping downwards gains some more speed */
if(x){
for(i=blockn-1; i>0; i-=blocksize){
e[i ]=x[i ]-y[i ]; sum0+=e[i ]*e[i ];
j1=i-1; e[j1]=x[j1]-y[j1]; sum1+=e[j1]*e[j1];
j2=i-2; e[j2]=x[j2]-y[j2]; sum2+=e[j2]*e[j2];
j3=i-3; e[j3]=x[j3]-y[j3]; sum3+=e[j3]*e[j3];
j4=i-4; e[j4]=x[j4]-y[j4]; sum0+=e[j4]*e[j4];
j5=i-5; e[j5]=x[j5]-y[j5]; sum1+=e[j5]*e[j5];
j6=i-6; e[j6]=x[j6]-y[j6]; sum2+=e[j6]*e[j6];
j7=i-7; e[j7]=x[j7]-y[j7]; sum3+=e[j7]*e[j7];
}
/*
* There may be some left to do.
* This could be done as a simple for() loop,
* but a switch is faster (and more interesting)
*/
i=blockn;
if(i<n){
/* Jump into the case at the place that will allow
* us to finish off the appropriate number of items.
*/
switch(n - i){
case 7 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;
case 6 : e[i]=x[i]-y[i]; sum1+=e[i]*e[i]; ++i;
case 5 : e[i]=x[i]-y[i]; sum2+=e[i]*e[i]; ++i;
case 4 : e[i]=x[i]-y[i]; sum3+=e[i]*e[i]; ++i;
case 3 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;
case 2 : e[i]=x[i]-y[i]; sum1+=e[i]*e[i]; ++i;
case 1 : e[i]=x[i]-y[i]; sum2+=e[i]*e[i]; //++i;
}
}
}
else{ /* x==0 */
for(i=blockn-1; i>0; i-=blocksize){
e[i ]=-y[i ]; sum0+=e[i ]*e[i ];
j1=i-1; e[j1]=-y[j1]; sum1+=e[j1]*e[j1];
j2=i-2; e[j2]=-y[j2]; sum2+=e[j2]*e[j2];
j3=i-3; e[j3]=-y[j3]; sum3+=e[j3]*e[j3];
j4=i-4; e[j4]=-y[j4]; sum0+=e[j4]*e[j4];
j5=i-5; e[j5]=-y[j5]; sum1+=e[j5]*e[j5];
j6=i-6; e[j6]=-y[j6]; sum2+=e[j6]*e[j6];
j7=i-7; e[j7]=-y[j7]; sum3+=e[j7]*e[j7];
}
/*
* There may be some left to do.
* This could be done as a simple for() loop,
* but a switch is faster (and more interesting)
*/
i=blockn;
if(i<n){
/* Jump into the case at the place that will allow
* us to finish off the appropriate number of items.
*/
switch(n - i){
case 7 : e[i]=-y[i]; sum0+=e[i]*e[i]; ++i;
case 6 : e[i]=-y[i]; sum1+=e[i]*e[i]; ++i;
case 5 : e[i]=-y[i]; sum2+=e[i]*e[i]; ++i;
case 4 : e[i]=-y[i]; sum3+=e[i]*e[i]; ++i;
case 3 : e[i]=-y[i]; sum0+=e[i]*e[i]; ++i;
case 2 : e[i]=-y[i]; sum1+=e[i]*e[i]; ++i;
case 1 : e[i]=-y[i]; sum2+=e[i]*e[i]; //++i;
}
}
}
return sum0+sum1+sum2+sum3;
}
/* undefine everything. THIS MUST REMAIN AT THE END OF THE FILE */
#undef POTF2
#undef GESVD
#undef GESDD
#undef GEMM
#undef LEVMAR_PSEUDOINVERSE
#undef LEVMAR_LUINVERSE
#undef LEVMAR_BOX_CHECK
#undef LEVMAR_CHOLESKY
#undef LEVMAR_COVAR
#undef LEVMAR_STDDEV
#undef LEVMAR_CORCOEF
#undef LEVMAR_R2
#undef LEVMAR_CHKJAC
#undef LEVMAR_FDIF_FORW_JAC_APPROX
#undef LEVMAR_FDIF_CENT_JAC_APPROX
#undef LEVMAR_TRANS_MAT_MAT_MULT
#undef LEVMAR_L2NRMXMY

30
lmfit/COPYING Normal file
View File

@@ -0,0 +1,30 @@
The package lmfit is distributed under the FreeBSD License:
--
Copyright (c) 1980-1999 University of Chicago,
as operator of Argonne National Laboratory
Copyright (c) 2004-2015 Joachim Wuttke, Forschungszentrum Juelich GmbH
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
This software is provided by the copyright holders and contributors "as is"
and any express or implied warranties, including, but not limited to, the
implied warranties of merchantability and fitness for a particular purpose
are disclaimed. In no event shall the copyright holder or contributors
be liable for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or business
interruption) however caused and on any theory of liability, whether in
contract, strict liability, or tort (including negligence or otherwise)
arising in any way out of the use of this software, even if advised of the
possibility of such damage.
--

52
lmfit/lmcurve.c Normal file
View File

@@ -0,0 +1,52 @@
/*
* Library: lmfit (Levenberg-Marquardt least squares fitting)
*
* File: lmcurve.c
*
* Contents: Implements lmcurve, a simplified API for curve fitting
* using the generic Levenberg-Marquardt routine lmmin.
*
* Copyright: Joachim Wuttke, Forschungszentrum Juelich GmbH (2004-2013)
*
* License: see ../COPYING (FreeBSD)
*
* Homepage: apps.jcns.fz-juelich.de/lmfit
*
* Note to programmers: Don't patch and fork, but copy and modify!
* If you need to compute residues differently, then please do not patch
* lmcurve.h and lmcurve.c, but copy them, and create differently named
* versions of lmcurve_data_struct, lmcurve_evaluate, and lmcurve of your own.
*/
#include "lmmin.h"
typedef struct {
const double *const t;
const double *const y;
double (*const g) (const double t, const double *par);
} lmcurve_data_struct;
void lmcurve_evaluate(
const double *const par, const int m_dat, const void *const data,
double *const fvec, int *const info)
{
for (int i = 0; i < m_dat; i++ )
fvec[i] =
((lmcurve_data_struct*)data)->y[i] -
((lmcurve_data_struct*)data)->g(
((lmcurve_data_struct*)data)->t[i], par );
}
void lmcurve(
const int n_par, double *const par, const int m_dat,
const double *const t, const double *const y,
double (*const g)(const double t, const double *const par),
const lm_control_struct *const control, lm_status_struct *const status)
{
lmcurve_data_struct data = {t, y, g};
lmmin(n_par, par, m_dat, NULL, (const void *const) &data,
lmcurve_evaluate, control, status);
}

45
lmfit/lmcurve.h Normal file
View File

@@ -0,0 +1,45 @@
/*
* Library: lmfit (Levenberg-Marquardt least squares fitting)
*
* File: lmcurve.h
*
* Contents: Declares lmcurve, a simplified API for curve fitting
* using the generic Levenberg-Marquardt routine lmmin.
*
* Copyright: Joachim Wuttke, Forschungszentrum Juelich GmbH (2004-2013)
*
* License: see ../COPYING (FreeBSD)
*
* Homepage: apps.jcns.fz-juelich.de/lmfit
*
* Note to programmers: Don't patch and fork, but copy and variate!
* If you need to compute residues differently, then please do not patch
* lmcurve.h, but copy it to a differently named file, and change lmcurve()
* into a differently named function declaration, like we have done in
* lmcurve_tyd.h.
*/
#ifndef LMCURVE_H
#define LMCURVE_H
#undef __BEGIN_DECLS
#undef __END_DECLS
#ifdef __cplusplus
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS /* empty */
#define __END_DECLS /* empty */
#endif
#include<lmstruct.h>
__BEGIN_DECLS
void lmcurve(
const int n_par, double* par, const int m_dat,
const double* t, const double* y,
double (*g)(const double t, const double* par),
const lm_control_struct* control, lm_status_struct* status);
__END_DECLS
#endif /* LMCURVE_H */

39
lmfit/lmcurve_tyd.h Normal file
View File

@@ -0,0 +1,39 @@
/*
* Library: lmfit (Levenberg-Marquardt least squares fitting)
*
* File: lmcurve_tyd.h
*
* Contents: Declares lmcurve_tyd(), a variant of lmcurve() that weighs
* data points y(t) with the inverse of the standard deviations dy.
*
* Copyright: Joachim Wuttke, Forschungszentrum Juelich GmbH (2004-2013)
*
* License: see ../COPYING (FreeBSD)
*
* Homepage: apps.jcns.fz-juelich.de/lmfit
*/
#ifndef LMCURVETYD_H
#define LMCURVETYD_H
#undef __BEGIN_DECLS
#undef __END_DECLS
#ifdef __cplusplus
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS /* empty */
#define __END_DECLS /* empty */
#endif
#include <lmstruct.h>
__BEGIN_DECLS
void lmcurve_tyd(
const int n_par, double* par, const int m_dat,
const double* t, const double* y, const double* dy,
double (*f)(double t, const double* par),
const lm_control_struct* control, lm_status_struct* status);
__END_DECLS
#endif /* LMCURVETYD_H */

1283
lmfit/lmmin.c Normal file

File diff suppressed because it is too large Load Diff

84
lmfit/lmmin.h Normal file
View File

@@ -0,0 +1,84 @@
/*
* Library: lmfit (Levenberg-Marquardt least squares fitting)
*
* File: lmmin.h
*
* Contents: Declarations for Levenberg-Marquardt minimization.
*
* Copyright: Joachim Wuttke, Forschungszentrum Juelich GmbH (2004-2013)
*
* License: see ../COPYING (FreeBSD)
*
* Homepage: apps.jcns.fz-juelich.de/lmfit
*/
#ifndef LMMIN_H
#define LMMIN_H
#undef __BEGIN_DECLS
#undef __END_DECLS
#ifdef __cplusplus
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS /* empty */
#define __END_DECLS /* empty */
#endif
#include "lmstruct.h"
__BEGIN_DECLS
/* Levenberg-Marquardt minimization. */
void lmmin(
const int n_par, double* par, const int m_dat, const double* y,
const void* data,
void (*evaluate)(
const double* par, const int m_dat, const void* data,
double* fvec, int* userbreak),
const lm_control_struct* control, lm_status_struct* status);
/*
* This routine contains the core algorithm of our library.
*
* It minimizes the sum of the squares of m nonlinear functions
* in n variables by a modified Levenberg-Marquardt algorithm.
* The function evaluation is done by the user-provided routine 'evaluate'.
* The Jacobian is then calculated by a forward-difference approximation.
*
* Parameters:
*
* n_par is the number of variables (INPUT, positive integer).
*
* par is the solution vector (INPUT/OUTPUT, array of length n).
* On input it must be set to an estimated solution.
* On output it yields the final estimate of the solution.
*
* m_dat is the number of functions to be minimized (INPUT, positive integer).
* It must fulfill m>=n.
*
* y contains data to be fitted. Use a null pointer if there are no data.
*
* data is a pointer that is ignored by lmmin; it is however forwarded
* to the user-supplied functions evaluate and printout.
* In a typical application, it contains experimental data to be fitted.
*
* evaluate is a user-supplied function that calculates the m functions.
* Parameters:
* n, x, m, data as above.
* fvec is an array of length m; on OUTPUT, it must contain the
* m function values for the parameter vector x.
* userbreak is an integer pointer. When *userbreak is set to a
* nonzero value, lmmin will terminate.
*
* control contains INPUT variables that control the fit algorithm,
* as declared and explained in lmstruct.h
*
* status contains OUTPUT variables that inform about the fit result,
* as declared and explained in lmstruct.h
*/
/* Refined calculation of Eucledian norm. */
double lm_enorm(const int, const double*);
double lm_fnorm(const int, const double*, const double*);
__END_DECLS
#endif /* LMMIN_H */

81
lmfit/lmstruct.h Normal file
View File

@@ -0,0 +1,81 @@
/*
* Library: lmfit (Levenberg-Marquardt least squares fitting)
*
* File: lmstruct.h
*
* Contents: Declarations of parameter records, used in lmmin.h and lmcurve.h
*
* Copyright: Joachim Wuttke, Forschungszentrum Juelich GmbH (2004-2013)
*
* License: see ../COPYING (FreeBSD)
*
* Homepage: apps.jcns.fz-juelich.de/lmfit
*/
#ifndef LMSTRUCT_H
#define LMSTRUCT_H
#undef __BEGIN_DECLS
#undef __END_DECLS
#ifdef __cplusplus
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS /* empty */
#define __END_DECLS /* empty */
#endif
__BEGIN_DECLS
#include <stdio.h>
/* Collection of input parameters for fit control. */
typedef struct {
double ftol; /* Relative error desired in the sum of squares.
Termination occurs when both the actual and
predicted relative reductions in the sum of squares
are at most ftol. */
double xtol; /* Relative error between last two approximations.
Termination occurs when the relative error between
two consecutive iterates is at most xtol. */
double gtol; /* Orthogonality desired between fvec and its derivs.
Termination occurs when the cosine of the angle
between fvec and any column of the Jacobian is at
most gtol in absolute value. */
double epsilon; /* Step used to calculate the Jacobian, should be
slightly larger than the relative error in the
user-supplied functions. */
double stepbound; /* Used in determining the initial step bound. This
bound is set to the product of stepbound and the
Euclidean norm of diag*x if nonzero, or else to
stepbound itself. In most cases stepbound should lie
in the interval (0.1,100.0). Generally, the value
100.0 is recommended. */
int patience; /* Used to set the maximum number of function evaluations
to patience*(number_of_parameters+1). */
int scale_diag; /* If 1, the variables will be rescaled internally.
Recommended value is 1. */
FILE* msgfile; /* Progress messages will be written to this file. */
int verbosity; /* OR'ed: 1: print some messages; 2: print Jacobian. */
int n_maxpri; /* -1, or max number of parameters to print. */
int m_maxpri; /* -1, or max number of residuals to print. */
} lm_control_struct;
/* Collection of output parameters for status info. */
typedef struct {
double fnorm; /* norm of the residue vector fvec. */
int nfev; /* actual number of iterations. */
int outcome; /* Status indicator. Nonnegative values are used as index
for the message text lm_infmsg, set in lmmin.c. */
int userbreak; /* Set when function evaluation requests termination. */
} lm_status_struct;
/* Preset (and recommended) control parameter settings. */
extern const lm_control_struct lm_control_double;
extern const lm_control_struct lm_control_float;
/* Preset message texts. */
extern const char* lm_infmsg[];
extern const char* lm_shortmsg[];
__END_DECLS
#endif /* LMSTRUCT_H */

View File

@@ -29,7 +29,7 @@ void QwtPlotGappedCurve::drawSeries(QPainter *painter, const QwtScaleMap &xMap,
return;
if (to < 0)
to = dataSize() - 1;
to = dataSize();
int i = from;
double last = 0;
@@ -38,7 +38,11 @@ void QwtPlotGappedCurve::drawSeries(QPainter *painter, const QwtScaleMap &xMap,
// First non-missed point will be the start of curve section.
double x = sample(i).x();
double y = sample(i).y();
if ((y < (naValue_ + -0.001) || y > (naValue_ + 0.001)) && x - last <= gapValue_) {
double yprev = 0;
if (i>0) yprev = sample(i-1).y();
if ((y < (naValue_ + -0.001) || y > (naValue_ + 0.001)) && (x - last <= gapValue_) &&
(yprev < (naValue_ + -0.001) || yprev > (naValue_ + 0.001))) {
int start = i-1;
int end = i;

Some files were not shown because too many files have changed in this diff Show More