From ae6d00103e6486c17a488e803831dfa5ddcebe3d Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Date: Fri, 15 Dec 2017 11:56:55 -0300 Subject: [PATCH] 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") --- src/Python/SIP/Bindings.cpp | 66 +++++++++++++++++++++ src/Python/SIP/Bindings.h | 1 + src/Python/SIP/goldencheetah.sip | 1 + src/Python/SIP/sipAPIgoldencheetah.h | 30 +++++----- src/Python/SIP/sipgoldencheetahBindings.cpp | 36 ++++++++++- src/Python/SIP/sipgoldencheetahcmodule.cpp | 1 + 6 files changed, 120 insertions(+), 15 deletions(-) diff --git a/src/Python/SIP/Bindings.cpp b/src/Python/SIP/Bindings.cpp index 2e94586cd..ca770bc0e 100644 --- a/src/Python/SIP/Bindings.cpp +++ b/src/Python/SIP/Bindings.cpp @@ -411,6 +411,72 @@ Bindings::seasonMetrics(bool all, DateRange range, QString filter) const return dict; } +PythonDataSeries* +Bindings::metrics(QString metric, bool all, QString filter) const +{ + Context *context = python->contexts.value(threadid()); + if (context == NULL || context->athlete == NULL || context->athlete->rideCache == NULL) return NULL; + + // how many rides to return if we're limiting to the + // currently selected date range ? + DateRange range = context->currentDateRange(); + + // apply any global filters + Specification specification; + FilterSet fs; + fs.addFilter(context->isfiltered, context->filters); + fs.addFilter(context->ishomefiltered, context->homeFilters); + + // did call contain a filter? + if (filter != "") { + + DataFilter dataFilter(python->chart, context); + QStringList files; + dataFilter.parseFilter(context, filter, &files); + fs.addFilter(true, files); + } + + specification.setFilterSet(fs); + + // we need to count rides that are in range... + int rides = 0; + foreach(RideItem *ride, context->athlete->rideCache->rides()) { + if (!specification.pass(ride)) continue; + if (all || range.pass(ride->dateTime.date())) rides++; + } + + const RideMetricFactory &factory = RideMetricFactory::instance(); + bool useMetricUnits = context->athlete->useMetricUnits; + for(int i=0; ispecialFields.internalName(factory.rideMetric(symbol)->name()); + name = name.replace(" ","_"); + name = name.replace("'","_"); + + if (name == metric) { + + // found, set an array of metric values + PythonDataSeries* pds = new PythonDataSeries(name, rides); + + int idx = 0; + foreach(RideItem *item, context->athlete->rideCache->rides()) { + if (!specification.pass(item)) continue; + if (all || range.pass(item->dateTime.date())) { + pds->data[idx++] = item->metrics()[i] * (useMetricUnits ? 1.0f : m->conversion()) + (useMetricUnits ? 0.0f : m->conversionSum()); + } + } + + // Done, return the series + return pds; + } + } + + // Not found, nothing to return + return NULL; +} + int Bindings::webpage(QString url) const { diff --git a/src/Python/SIP/Bindings.h b/src/Python/SIP/Bindings.h index 293222bb5..0f680d4e5 100644 --- a/src/Python/SIP/Bindings.h +++ b/src/Python/SIP/Bindings.h @@ -35,6 +35,7 @@ class Bindings { // working with metrics PyObject* activityMetrics(bool compare=false) const; PyObject* seasonMetrics(bool all=false, QString filter=QString(), bool compare=false) const; + PythonDataSeries *metrics(QString metric, bool all=false, QString filter=QString()) const; // working with the web view int webpage(QString url) const; diff --git a/src/Python/SIP/goldencheetah.sip b/src/Python/SIP/goldencheetah.sip index 99ff087ee..fa3bdcb24 100644 --- a/src/Python/SIP/goldencheetah.sip +++ b/src/Python/SIP/goldencheetah.sip @@ -125,6 +125,7 @@ public: // working with metrics PyObject* activityMetrics(bool compare=false) /TransferBack/; PyObject* seasonMetrics(bool all=false, QString filter=QString(), bool compare=false) /TransferBack/; + PythonDataSeries *metrics(QString metric, bool all=false, QString filter=QString()) /TransferBack/; // working with the web view int webpage(QString url) const; diff --git a/src/Python/SIP/sipAPIgoldencheetah.h b/src/Python/SIP/sipAPIgoldencheetah.h index 86337b94e..6b77a221c 100644 --- a/src/Python/SIP/sipAPIgoldencheetah.h +++ b/src/Python/SIP/sipAPIgoldencheetah.h @@ -35,20 +35,22 @@ #define sipName_Bindings &sipStrings_goldencheetah[118] #define sipNameNr_webpage 127 #define sipName_webpage &sipStrings_goldencheetah[127] -#define sipNameNr_version 135 -#define sipName_version &sipStrings_goldencheetah[135] -#define sipNameNr_athlete 143 -#define sipName_athlete &sipStrings_goldencheetah[143] -#define sipNameNr___len__ 151 -#define sipName___len__ &sipStrings_goldencheetah[151] -#define sipNameNr___str__ 159 -#define sipName___str__ &sipStrings_goldencheetah[159] -#define sipNameNr_QString 167 -#define sipName_QString &sipStrings_goldencheetah[167] -#define sipNameNr_series 175 -#define sipName_series &sipStrings_goldencheetah[175] -#define sipNameNr_build 182 -#define sipName_build &sipStrings_goldencheetah[182] +#define sipNameNr_metrics 135 +#define sipName_metrics &sipStrings_goldencheetah[135] +#define sipNameNr_version 143 +#define sipName_version &sipStrings_goldencheetah[143] +#define sipNameNr_athlete 151 +#define sipName_athlete &sipStrings_goldencheetah[151] +#define sipNameNr___len__ 159 +#define sipName___len__ &sipStrings_goldencheetah[159] +#define sipNameNr___str__ 167 +#define sipName___str__ &sipStrings_goldencheetah[167] +#define sipNameNr_QString 175 +#define sipName_QString &sipStrings_goldencheetah[175] +#define sipNameNr_series 183 +#define sipName_series &sipStrings_goldencheetah[183] +#define sipNameNr_build 190 +#define sipName_build &sipStrings_goldencheetah[190] #define sipMalloc sipAPI_goldencheetah->api_malloc #define sipFree sipAPI_goldencheetah->api_free diff --git a/src/Python/SIP/sipgoldencheetahBindings.cpp b/src/Python/SIP/sipgoldencheetahBindings.cpp index f7e18e2af..5cc6b0a6b 100644 --- a/src/Python/SIP/sipgoldencheetahBindings.cpp +++ b/src/Python/SIP/sipgoldencheetahBindings.cpp @@ -278,6 +278,39 @@ static PyObject *meth_Bindings_seasonMetrics(PyObject *sipSelf, PyObject *sipArg } +extern "C" {static PyObject *meth_Bindings_metrics(PyObject *, PyObject *);} +static PyObject *meth_Bindings_metrics(PyObject *sipSelf, PyObject *sipArgs) +{ + PyObject *sipParseErr = NULL; + + { + ::QString* a0; + int a0State = 0; + bool a1 = 0; + ::QString a2def = QString(); + ::QString* a2 = &a2def; + int a2State = 0; + ::Bindings *sipCpp; + + if (sipParseArgs(&sipParseErr, sipArgs, "BJ1|bJ1", &sipSelf, sipType_Bindings, &sipCpp, sipType_QString,&a0, &a0State, &a1, sipType_QString,&a2, &a2State)) + { + ::PythonDataSeries*sipRes; + + sipRes = sipCpp->metrics(*a0,a1,*a2); + sipReleaseType(a0,sipType_QString,a0State); + sipReleaseType(a2,sipType_QString,a2State); + + return sipConvertFromType(sipRes,sipType_PythonDataSeries,Py_None); + } + } + + /* Raise an exception if the arguments couldn't be parsed. */ + sipNoMethod(sipParseErr, sipName_Bindings, sipName_metrics, NULL); + + return NULL; +} + + extern "C" {static PyObject *meth_Bindings_webpage(PyObject *, PyObject *);} static PyObject *meth_Bindings_webpage(PyObject *sipSelf, PyObject *sipArgs) { @@ -378,6 +411,7 @@ static PyMethodDef methods_Bindings[] = { {SIP_MLNAME_CAST(sipName_activityMetrics), meth_Bindings_activityMetrics, METH_VARARGS, NULL}, {SIP_MLNAME_CAST(sipName_athlete), meth_Bindings_athlete, METH_VARARGS, NULL}, {SIP_MLNAME_CAST(sipName_build), meth_Bindings_build, METH_VARARGS, NULL}, + {SIP_MLNAME_CAST(sipName_metrics), meth_Bindings_metrics, METH_VARARGS, NULL}, {SIP_MLNAME_CAST(sipName_seasonMetrics), meth_Bindings_seasonMetrics, METH_VARARGS, NULL}, {SIP_MLNAME_CAST(sipName_series), meth_Bindings_series, METH_VARARGS, NULL}, {SIP_MLNAME_CAST(sipName_seriesLast), meth_Bindings_seriesLast, METH_VARARGS, NULL}, @@ -402,7 +436,7 @@ sipClassTypeDef sipTypeDef_goldencheetah_Bindings = { { sipNameNr_Bindings, {0, 0, 1}, - 11, methods_Bindings, + 12, methods_Bindings, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, diff --git a/src/Python/SIP/sipgoldencheetahcmodule.cpp b/src/Python/SIP/sipgoldencheetahcmodule.cpp index 45aba25de..48107740b 100644 --- a/src/Python/SIP/sipgoldencheetahcmodule.cpp +++ b/src/Python/SIP/sipgoldencheetahcmodule.cpp @@ -26,6 +26,7 @@ const char sipStrings_goldencheetah[] = { 't', 'h', 'r', 'e', 'a', 'd', 'i', 'd', 0, 'B', 'i', 'n', 'd', 'i', 'n', 'g', 's', 0, 'w', 'e', 'b', 'p', 'a', 'g', 'e', 0, + 'm', 'e', 't', 'r', 'i', 'c', 's', 0, 'v', 'e', 'r', 's', 'i', 'o', 'n', 0, 'a', 't', 'h', 'l', 'e', 't', 'e', 0, '_', '_', 'l', 'e', 'n', '_', '_', 0,