Commit Graph

55 Commits

Author SHA1 Message Date
Ale Martinez
698ea4eb0b Added ScriptContext for Python APIs called from DataFilter scripts
Carry RideItem, Specification and Metrics to consider the cases when
the script is part of a UserMetric or an LTMPlot formula
Python series, activityWbal and activityXdata honor RideItem and Specification
Python activityMetrics honors ScriptContext RideItem and Metrics
Python activityMeanMax honors ScriptContext RideItem
Force recomputation of metrics just in case Python Scripts were used before
2018-04-08 10:59:43 -03:00
Mark Liversedge
49d78e6c7b Remove TrainingPeaks Trademarks
.. renaming the 3 metrics they trademarked in 2013:

   TSS => BikeStress
   IF => BikeIntensity
   NP => IsoPower

.. this will break data filters, user formula and
   R and Python charts.

.. in the next commit will add user metrics to ensure
   backward compatibility.
2018-02-17 11:12:50 +00:00
TuxedoFish
1dc00b8bd3 Setenv PYTHONHOME not Py_SetPythonHome
.. what a clusterfuck the Python embedding API is. If you set PYTHONHOME
   it loses PYTHONPATH. But only on a Mac. Go figure.

.. so we just set the environment to the user defined value in prefs.
2018-02-15 15:57:02 +00:00
Mark Liversedge
ef68066f7f Don't bug user if R/Python not compatible
.. most users don't care and will freak out.

.. also set PYTHONHOME if user specified (this helps users on
   MacOS use their local modules).
2018-02-15 15:10:30 +00:00
TuxedoFish
47f439d1bc Fixup Python search for Mac
.. PYTHONHOME/bin/python3 not PYTHONHOME/python3 on MacOS when installed
   within the framework directory.
2018-02-11 17:06:29 +00:00
Mark Liversedge
b50c034f4e Python Startup 2 of 2
.. honour PYTHONHOME environment variable

.. allow user to set PYTHONHOME in preferences, and check its a decent
   value before setting it.
2018-02-10 20:39:40 +00:00
Mark Liversedge
6d78bd165c Python Startup 1 of 2 Windows Fixups
.. fixup trivial issues like PATHSEP and separators in general.

.. it seems that Py_SetProgramName will drive the initialisation of the
   Python interpreter to set sys.path, sys.prefix and sys.exec_prefix.

.. rather than trying to fixup these directly instead we set the program
   name to the python installed binary (full path).

.. you still need python in your path, will fixup in part 2.

.. lastly, also added a 'printd' macro to embed debug info, which can
   be enabled in gcconfig.pri via DEFINES += PYTHON_DEBUG=true
2018-02-10 10:16:24 +00:00
Mark Liversedge
710cddf664 Python Startup 1 of 2
.. look for python in path and check version and module path, then
   use this when initialising to ensure the installed modules
   are used, not the local copy.

.. needs testing on Windows and need to enable the user to specify
   the location of Python so users don't need to modify PATH.
2018-02-09 19:30:35 +00:00
Mark Liversedge
954570fe16 Python Embedding is optional and check install
.. make python embedding optional, if it's not installed then
   disable in preferences (new checkbox similar to R).
2018-02-05 16:27:00 +00:00
Mark Liversedge
8e3a170d94 DataFilter Embed Python Scripts
.. allow the user to embed a python script into a datafilter.

.. this is primarily to enable the use of python when writing
   user metrics.

.. the syntax is basically "%%python script %%" and it is
   evaluated as an expresssion so the results can be assigned
   to a variable or returned as a value.

.. additionally GC.result(double) has been added to the python
   API to enable a return value to be set by the script.

.. since Python is really sensitive about white space its going
   to be best practice to embed python scripts without honoring
   any of the data filter spacing, for example:

{
   value {
      t <-

%%python
GC.result(100)
%%;

   }
}

  .. is likely to be a sensible way to use this.

  .. also notice how the ; is needed after the expression. This
     is because %%python ... %% is a numeric expression with the
     same semantics as "1 + 2"
2018-01-29 10:03:41 +00:00
Alejandro Martinez
8a3db53a90 Rename some Python entry points to match the wiki
zones => athleteZones
wbal => activityWbal
xdataseries => activityXdata
pmc => seasonPmc
measures => seasonMeasures
2018-01-23 17:56:24 -03:00
Alejandro Martinez
0c4ffcf93f Add Python seasonPeaks(series, duration, all=False, filter="", compare=False)
Similar to R season.peaks but for one series/duration at a time
2018-01-23 17:24:11 -03:00
Alejandro Martinez
b293d5374b Add Python seasonIntervals(type="", compare=False)
Get metrics for intervals in a season, similar to
R GC.season.intervals
2018-01-22 21:46:23 -03:00
Alejandro Martinez
9d00f78e4c Add Python zones(date, sport)
To retrieve athletes zones info, similar to R athlete.zones,
just returning a dict instead of a data frame
2018-01-20 15:05:34 -03:00
Alejandro Martinez
9e193c7e9f Changed Python athlete to return a dict
Similar to the R counterpart it includes name, home, dob,
weight, height and gender
2018-01-19 20:41:21 -03:00
Alejandro Martinez
90a18303c4 Add Python xdataseries(name, series, join="repeat", activity=None)
Similar to series but used to retrieve an XData series, like the R
activity.xdata counterpart, for example: GC.xdataseries("SWIM", "STROKES")
NB: I reserved xdata(name) to retrive a whole group of series by name
with its own sampling, not implemented in this commit.
2018-01-18 15:41:48 -03:00
Alejandro Martinez
6df60d819b Add Python wbal similar to series
Optional parameter is activity datetime, current activity if not provided.
2018-01-17 14:55:16 -03:00
Mark Liversedge
b1e0a567fb rideFileCacheMeanmax just fix first date. 2017-12-24 11:11:00 +00:00
Alejandro Martinez
cc2f56c7a3 Python season(all=False, compare=False)
Similar to R season(), retuns a dict with name, from, to and color lists.
2017-12-21 15:19:14 -03:00
Mark Liversedge
3304e6c72e Fix Linux SEGV for symbol conflict
.. mad conflict .. where scipy.stats.linregress conflicts
   with a sndfile and crashes when calling sf_check_fpe

.. see fix stolen from here: https://github.com/scipy/scipy/issues/8130
2017-12-21 16:42:08 +00:00
Alejandro Martinez
9599060768 Python rideFileCacheMeanmax() remove dangling code
To precompute the number of series was necessary for R but not for Python
2017-12-20 18:27:36 -03:00
Mark Liversedge
6495fe8505 Python rideFileCacheMeanmax() fixups
.. check for valid date
.. always add power_date (to match logic at start)
2017-12-20 09:56:33 +00:00
Alejandro Martinez
5d94ce2167 Python activity, series and seriesPresent optional datetime parameter
It can be used to get data from other than current selected activiy,
identified by datetime, s.t. the items returned by activities(filter)
2017-12-18 20:55:42 -03:00
Alejandro Martinez
6b7d1b794c Python activities(filter="")
Returns a list of DateTime for activities passing the filter
2017-12-17 17:57:55 -03:00
Alejandro Martinez
f47607d725 Python measures(all=False, group="Body")
Similar to R measures returning a dict with a list for each
measure field in the requested group (Body or Hrv).
2017-12-17 13:00:17 -03:00
Alejandro Martinez
bbfc4e44fe Python pmc(all=False, metric="TSS")
Similar to R pmc, returns a dict with a list for: date, stress, lts, sts, sb, rr
2017-12-17 11:28:16 -03:00
Alejandro Martinez
33b86235e9 Enable compare mode for Python activityMeanmax and seasonMeanmax
Usage is similar to the R versions
2017-12-16 18:44:45 -03:00
Alejandro Martinez
1aa1ab41d1 Python activityMeanmax and seasonMeanmax
Both return a dict with a list for each supported series from cache
Next step is to support compare mode
2017-12-16 17:43:03 -03:00
Alejandro Martinez
be73ab9749 Enable keyword arguments in Python wrappers generated by SIP
For example:
>>> GC.metrics("Pace", filter="isRun<>0")
is equivalent to:
>>> GC.metrics("Pace", False, "isRun<>0")
as expected by Python users
2017-12-15 19:42:25 -03:00
Alejandro Martinez
ae6d00103e Python metrics(metric, all, filter)
A more efficient way to obtain a metric series for a large number
of activities, it can be converted to numpy array without copy:
import numpy as np
nparray = np.asarray(GC.metrics("Average_Power", True, "isRun=0 && isSwim=0")
2017-12-15 11:56:55 -03:00
Alejandro Martinez
eae7f1d9ed Add Python seasonMetrics(all, filter, compare)
Similar to R API season.metrics
2017-12-14 17:30:32 -03:00
Alejandro Martinez
9a48237543 Make PythonDataSeries independent of RideFile
To reuse it for other double series s.t. metrics or mean maximal data
2017-12-13 11:52:08 -03:00
Alejandro Martinez
d7579beed1 Add Color to Python activityMetrics
Using name "color" and renamed "date"/"time" for compatibility with R API
2017-12-13 09:30:29 -03:00
Alejandro Martinez
a3e23fd6de Enabled compare for Python activiyMetrics
activityMetrics(True) returns a list of 2 element tuples with
metrics&metadata dict as first element and color name as second one.
2017-12-12 21:29:39 -03:00
Alejandro Martinez
da6db1eb6b Add Date and Time to Python activityMetrics
PyDateTime_IMPORT needs to be called in the same module where
datetime macros are used to avoid a crash.
2017-12-12 13:52:18 -03:00
Alejandro Martinez
a15bcfc102 Python activityMetrics
Returns a Python dict with metrics and metadata fields.
It doesn't implement compare mode yet.
2017-12-12 08:35:06 -03:00
Mark Liversedge
dd112d6d81 Python Webpage load via slots
.. to communicated across threads and avoid a crash.
2017-12-11 21:17:34 +00:00
Mark Liversedge
7eb926b33a Python Web Display
.. instead of an opengl canvas lets start with a Web canvas.

.. we might have options to use QtCharts or OpenGL later.

.. not working - committed to save WIP.
2017-12-11 18:58:59 +00:00
Mark Liversedge
a7981ff302 Python fixup ConvertTo_QString
.. missing in original code. will be needed for APIs that
   want to pass names etc to C++ from Python.
2017-12-11 12:32:33 +00:00
slorenz
80e786c4c0 Python Use UTF8 and untranslated Series Names
.. With german translation activated GC.activity() complains about
   some utf-8 decoding stuff and returns error.

   First I thought came from the real activity json file, but it's
   from translation: Altitude -> Höhenmeter.

   Is it necessary to use toLatin1() in goldencheetah.sip? With
   toUtf8() it works and you get delta symbols instead of question marks.

.. With R the series names are always in english and use a naming
   convention derived from the R trackR package -- we now follow the
   same in Python bindings to ensure charts created in one locale
   will continue to work in another.
2017-12-10 10:16:57 +00:00
Alejandro Martinez
b3680c0dd1 Enabled sequence behavior on PythonDataSeries
Adding __getitem__ makes it to behave like a sequence enabling indexing
and iteration,for example:
s = GC.series(6)
print(s[0], s[-1])
for v in s: print(s)
l = list(s)
print(l.count(0))
2017-12-09 20:36:03 -03:00
Mark Liversedge
385b56ee47 Python GC.activity()
.. very basic API as we develop out, it just returns a dict
   for now. Need to expand to enable returning a list if
   compare mode is active (like R).

.. implemented in a new source file Resources/python/library.py
   which is loaded directly after the interpreter is loaded at
   startup.

.. also updated src.pro to add library.py and goldencheetah.sip
   to OTHER_FILES so they can be edited easily in QtCreator.
2017-12-09 19:52:59 +00:00
Mark Liversedge
76eaecab5a Fixup Py_ssize_t on Windows VS build
.. Py_ssize_t is not always a long, so lets use the python
   type in our bindings to keep the buffer code simple.
2017-12-09 19:08:00 +00:00
Mark Liversedge
2a5fcfe5db Python DataSeries functions
.. start of API to work with ride data, exposing the raw
   sample data via the buffer protocol python api and SIP

.. adds utility functions that will ultimately be wrapped
   inside a python class/function:

   GC.series(n) - return series data as a python array
   GC.seriesName(n) - return string describing series data
   GC.seriesLast() - returns int for last series type
   GC.seriesPresent(n) - returns True if series in ride

.. example of using these functions in python to create a
   dict object collecting all available data:

   activity = {}
   for x in range(0, GC.seriesLast()):
      if (GC.seriesPresent(x)):
         activity[GC.seriesName(x)] = GC.series(x)
2017-12-09 16:50:29 +00:00
Mark Liversedge
3a534e1ff4 Python GC.build() and GC.version()
.. simple examples, lots of generated code changes which is
   not very helpful.

.. but the only files that were edited by hand are goldencheetah.sip
   Bindings.h and Bindings.cpp
2017-12-05 19:23:38 +00:00
Mark Liversedge
db3d119f7d Python GC.athlete()
Basic proof of concept for CPP binding using SIP but with
our own type conversion (to avoid overhead of SIP lib/deploy).
Its far from perfect but will serve as a starting point.

.. needed to fixup type conversion in goldencheetah.sip to
   convert returning QString as PyUnicode

.. needed to fixup passing context when multi-threaded

.. needed to fixup Bindings.h/cpp to offer new API
2017-12-04 15:20:43 +00:00
Mark Liversedge
6d9731e1ed Fixup SIP Makefile
.. to add API header to the dependency
2017-12-04 15:20:43 +00:00
Mark Liversedge
29558420b6 remove debug
.. sigh
2017-12-02 20:09:30 +00:00
Mark Liversedge
00144effd8 Python Module Framework
.. Using SIP thats used in PyQt et al we have a module
   called `goldencheetah' which includes bindings.

   Currently there is only a single method `getValue()'
   that returns 1. It's to get the basic plumbing in place.

   src/Python/SIP contains all the files related to the
   module. The cpp files are generated by the `sip' utility
   which will need to be available if you want to work on the
   bindings. Run make -f Makefile.hack to regenerate the cpp
   files if you edit them.

   I prefer to distribute the generated files at this point
   whilst development occurs. We may change that at a later
   date.

.. Please note that the gcconfig.pri.in file has changed as
   we now include the python include path rather than set a
   macro for the include directive (See PYTHONINCLUDES in
   gcconfig.pri.in)

.. lastly, to test this is working in a python chart console:
   > print(GC.getValue())
   1
   >
2017-12-02 16:33:54 +00:00
Mark Liversedge
14e27e9486 Python Editor Syntax Highlighter
.. basic stuff for now.
2017-11-25 08:59:56 +00:00