mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-04-15 05:32:21 +00:00
added power hist
This commit is contained in:
@@ -19,6 +19,7 @@ HEADERS += \
|
||||
LogTimeScaleDraw.h \
|
||||
LogTimeScaleEngine.h \
|
||||
MainWindow.h \
|
||||
PowerHist.h \
|
||||
RawFile.h \
|
||||
RideItem.h
|
||||
SOURCES += \
|
||||
@@ -29,6 +30,7 @@ SOURCES += \
|
||||
LogTimeScaleDraw.cpp \
|
||||
LogTimeScaleEngine.cpp \
|
||||
MainWindow.cpp \
|
||||
PowerHist.cpp \
|
||||
RawFile.cpp \
|
||||
RideItem.cpp \
|
||||
\
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "ChooseCyclistDialog.h"
|
||||
#include "CpintPlot.h"
|
||||
#include "DownloadRideDialog.h"
|
||||
#include "PowerHist.h"
|
||||
#include "RawFile.h"
|
||||
#include "RideItem.h"
|
||||
#include "Settings.h"
|
||||
@@ -152,6 +153,34 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
cpintPlot = new CpintPlot(home.path());
|
||||
tabWidget->addTab(cpintPlot, "Critical Power Plot");
|
||||
|
||||
window = new QWidget;
|
||||
vlayout = new QVBoxLayout;
|
||||
QHBoxLayout *binWidthLayout = new QHBoxLayout;
|
||||
QLabel *binWidthLabel = new QLabel(tr("Bin width (watts)"), window);
|
||||
binWidthLineEdit = new QLineEdit(window);
|
||||
binWidthLineEdit->setFixedWidth(30);
|
||||
|
||||
binWidthLayout->addWidget(binWidthLabel);
|
||||
binWidthLayout->addWidget(binWidthLineEdit);
|
||||
binWidthSlider = new QSlider(Qt::Horizontal);
|
||||
binWidthSlider->setTickPosition(QSlider::TicksBelow);
|
||||
binWidthSlider->setTickInterval(1);
|
||||
binWidthSlider->setMinimum(1);
|
||||
binWidthSlider->setMaximum(100);
|
||||
binWidthLineEdit->setValidator(new QIntValidator(binWidthSlider->minimum(),
|
||||
binWidthSlider->maximum(),
|
||||
binWidthLineEdit));
|
||||
binWidthLayout->addWidget(binWidthSlider);
|
||||
powerHist = new PowerHist();
|
||||
binWidthSlider->setValue(powerHist->binWidth());
|
||||
binWidthLineEdit->setText(QString("%1").arg(powerHist->binWidth()));
|
||||
vlayout->addWidget(powerHist);
|
||||
vlayout->addLayout(binWidthLayout);
|
||||
window->setLayout(vlayout);
|
||||
window->show();
|
||||
|
||||
tabWidget->addTab(window, "Power Histogram");
|
||||
|
||||
connect(treeWidget, SIGNAL(itemSelectionChanged()),
|
||||
this, SLOT(rideSelected()));
|
||||
connect(splitter, SIGNAL(splitterMoved(int,int)),
|
||||
@@ -170,6 +199,10 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
this, SLOT(setSmoothingFromSlider()));
|
||||
connect(smoothLineEdit, SIGNAL(returnPressed()),
|
||||
this, SLOT(setSmoothingFromLineEdit()));
|
||||
connect(binWidthSlider, SIGNAL(valueChanged(int)),
|
||||
this, SLOT(setBinWidthFromSlider()));
|
||||
connect(binWidthLineEdit, SIGNAL(returnPressed()),
|
||||
this, SLOT(setBinWidthFromLineEdit()));
|
||||
connect(tabWidget, SIGNAL(currentChanged(int)),
|
||||
this, SLOT(tabChanged(int)));
|
||||
|
||||
@@ -256,6 +289,7 @@ MainWindow::rideSelected()
|
||||
allPlot->setData(ride->raw);
|
||||
if (tabWidget->currentIndex() == 2)
|
||||
cpintPlot->calculate(ride->fileName, ride->dateTime);
|
||||
powerHist->setData(ride->raw);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -299,6 +333,25 @@ MainWindow::setSmoothingFromLineEdit()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::setBinWidthFromSlider()
|
||||
{
|
||||
if (powerHist->binWidth() != binWidthSlider->value()) {
|
||||
powerHist->setBinWidth(binWidthSlider->value());
|
||||
binWidthLineEdit->setText(QString("%1").arg(powerHist->binWidth()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::setBinWidthFromLineEdit()
|
||||
{
|
||||
int value = binWidthLineEdit->text().toInt();
|
||||
if (value != powerHist->binWidth()) {
|
||||
powerHist->setBinWidth(value);
|
||||
binWidthSlider->setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::tabChanged(int index)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
class AllPlot;
|
||||
class CpintPlot;
|
||||
class PowerHist;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
@@ -47,6 +48,8 @@ class MainWindow : public QMainWindow
|
||||
void downloadRide();
|
||||
void setSmoothingFromSlider();
|
||||
void setSmoothingFromLineEdit();
|
||||
void setBinWidthFromSlider();
|
||||
void setBinWidthFromLineEdit();
|
||||
void tabChanged(int index);
|
||||
|
||||
private:
|
||||
@@ -62,7 +65,10 @@ class MainWindow : public QMainWindow
|
||||
CpintPlot *cpintPlot;
|
||||
QSlider *smoothSlider;
|
||||
QLineEdit *smoothLineEdit;
|
||||
QSlider *binWidthSlider;
|
||||
QLineEdit *binWidthLineEdit;
|
||||
QTreeWidgetItem *allRides;
|
||||
PowerHist *powerHist;
|
||||
};
|
||||
|
||||
#endif // _GC_MainWindow_h
|
||||
|
||||
107
src/gui/PowerHist.cpp
Normal file
107
src/gui/PowerHist.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* $Id: PowerHist.cpp,v 1.2 2006/07/12 02:13:57 srhea Exp $
|
||||
*
|
||||
* Copyright (c) 2006 Sean C. Rhea (srhea@srhea.net)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "PowerHist.h"
|
||||
#include "RawFile.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include <qwt_plot_curve.h>
|
||||
#include <qwt_plot_grid.h>
|
||||
#include <qwt_legend.h>
|
||||
#include <qwt_data.h>
|
||||
|
||||
PowerHist::PowerHist() :
|
||||
array(NULL), binw(20)
|
||||
{
|
||||
setCanvasBackground(Qt::white);
|
||||
|
||||
setAxisTitle(xBottom, "Power (watts)");
|
||||
setAxisTitle(yLeft, "Cumulative Time (minutes)");
|
||||
|
||||
curve = new QwtPlotCurve("Power");
|
||||
curve->setStyle(QwtPlotCurve::Steps);
|
||||
curve->setRenderHint(QwtPlotItem::RenderAntialiased);
|
||||
curve->setPen(QPen(Qt::red));
|
||||
curve->attach(this);
|
||||
|
||||
grid = new QwtPlotGrid();
|
||||
grid->enableX(false);
|
||||
QPen gridPen;
|
||||
gridPen.setStyle(Qt::DotLine);
|
||||
grid->setPen(gridPen);
|
||||
grid->attach(this);
|
||||
}
|
||||
|
||||
void
|
||||
PowerHist::recalc()
|
||||
{
|
||||
int count = (int) ceil((arrayLength - 1) / binw);
|
||||
double *smoothWatts = new double[count+1];
|
||||
double *smoothTime = new double[count+1];
|
||||
int i;
|
||||
for (i = 0; i < count; ++i) {
|
||||
int low = i * binw;
|
||||
int high = low + binw;
|
||||
smoothWatts[i] = low;
|
||||
smoothTime[i] = 0.0;
|
||||
while (low < high)
|
||||
smoothTime[i] += array[low++];
|
||||
}
|
||||
smoothTime[i] = 0.0;
|
||||
smoothWatts[i] = i * binw;
|
||||
curve->setData(smoothWatts, smoothTime, count+1);
|
||||
setAxisScale(xBottom, 0.0, smoothWatts[count]);
|
||||
setYMax();
|
||||
replot();
|
||||
delete [] smoothWatts;
|
||||
delete [] smoothTime;
|
||||
}
|
||||
|
||||
void
|
||||
PowerHist::setYMax()
|
||||
{
|
||||
setAxisScale(yLeft, 0.0, curve->maxYValue() + 10.0);
|
||||
}
|
||||
|
||||
void
|
||||
PowerHist::setData(RawFile *raw)
|
||||
{
|
||||
setTitle(raw->startTime.toString(GC_DATETIME_FORMAT));
|
||||
int maxPower = (int) round(raw->powerHist.keys().last());
|
||||
delete [] array;
|
||||
arrayLength = maxPower + 1;
|
||||
array = new double[arrayLength];
|
||||
for (int i = 0; i < arrayLength; ++i)
|
||||
array[i] = 0.0;
|
||||
QMapIterator<double,double> i(raw->powerHist);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
array[(int) round(i.key())] += i.value();
|
||||
}
|
||||
recalc();
|
||||
}
|
||||
|
||||
void
|
||||
PowerHist::setBinWidth(int value)
|
||||
{
|
||||
binw = value;
|
||||
recalc();
|
||||
}
|
||||
|
||||
62
src/gui/PowerHist.h
Normal file
62
src/gui/PowerHist.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* $Id: PowerHist.h,v 1.2 2006/07/12 02:13:57 srhea Exp $
|
||||
*
|
||||
* Copyright (c) 2006 Sean C. Rhea (srhea@srhea.net)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef _GC_PowerHist_h
|
||||
#define _GC_PowerHist_h 1
|
||||
|
||||
#include <qwt_plot.h>
|
||||
|
||||
class QwtPlotCurve;
|
||||
class QwtPlotGrid;
|
||||
class RawFile;
|
||||
|
||||
class PowerHist : public QwtPlot
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
QwtPlotCurve *curve;
|
||||
|
||||
PowerHist();
|
||||
|
||||
int binWidth() const { return binw; }
|
||||
|
||||
void setData(RawFile *raw);
|
||||
|
||||
public slots:
|
||||
|
||||
void setBinWidth(int value);
|
||||
|
||||
protected:
|
||||
|
||||
QwtPlotGrid *grid;
|
||||
|
||||
double *array;
|
||||
int arrayLength;
|
||||
|
||||
int binw;
|
||||
|
||||
void recalc();
|
||||
void setYMax();
|
||||
};
|
||||
|
||||
#endif // _GC_PowerHist_h
|
||||
|
||||
@@ -27,14 +27,17 @@ extern "C" {
|
||||
struct RawFileReadState
|
||||
{
|
||||
QList<RawFilePoint*> &points;
|
||||
QMap<double,double> &powerHist;
|
||||
QStringList &errors;
|
||||
double last_secs, last_miles;
|
||||
unsigned last_interval;
|
||||
time_t start_since_epoch;
|
||||
unsigned rec_int;
|
||||
RawFileReadState(QList<RawFilePoint*> &points, QStringList &errors) :
|
||||
points(points), errors(errors), last_secs(0.0), last_miles(0.0),
|
||||
last_interval(0), start_since_epoch(0), rec_int(0) {}
|
||||
RawFileReadState(QList<RawFilePoint*> &points,
|
||||
QMap<double,double> &powerHist,
|
||||
QStringList &errors) :
|
||||
points(points), powerHist(powerHist), errors(errors), last_secs(0.0),
|
||||
last_miles(0.0), last_interval(0), start_since_epoch(0), rec_int(0) {}
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -72,6 +75,12 @@ data_cb(double secs, double nm, double mph, double watts, double miles,
|
||||
state->last_secs = secs;
|
||||
state->last_miles = miles;
|
||||
state->last_interval = interval;
|
||||
double sum = state->rec_int * 0.021;
|
||||
if (state->powerHist.contains(watts)) {
|
||||
sum += state->powerHist.value(watts);
|
||||
state->powerHist.remove(watts);
|
||||
}
|
||||
state->powerHist.insert(watts, sum);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -90,7 +99,7 @@ RawFile *RawFile::readFile(const QFile &file, QStringList &errors)
|
||||
}
|
||||
FILE *f = fdopen(result->file.handle(), "r");
|
||||
assert(f);
|
||||
RawFileReadState state(result->points, errors);
|
||||
RawFileReadState state(result->points, result->powerHist, errors);
|
||||
pt_read_raw(f, 0 /* not compat */, &state, config_cb,
|
||||
time_cb, data_cb, error_cb);
|
||||
result->rec_int = state.rec_int;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <QDateTime>
|
||||
#include <QFile>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QStringList>
|
||||
|
||||
struct RawFilePoint
|
||||
@@ -51,6 +52,7 @@ class RawFile
|
||||
QDateTime startTime;
|
||||
int rec_int;
|
||||
QList<RawFilePoint*> points;
|
||||
QMap<double,double> powerHist;
|
||||
static RawFile *readFile(const QFile &file, QStringList &errors);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user