Merge branch 'feature/trendline' into develop
This commit is contained in:
@@ -1373,6 +1373,9 @@ class AnalysisChoiceForm(forms.Form):
|
|||||||
required=False,
|
required=False,
|
||||||
label='Include Rest Strokes')
|
label='Include Rest Strokes')
|
||||||
|
|
||||||
|
trendline = forms.BooleanField(initial=False, required=False,
|
||||||
|
label='Trend Line')
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(AnalysisChoiceForm, self).__init__(*args, **kwargs)
|
super(AnalysisChoiceForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
@@ -1808,6 +1811,9 @@ class FlexOptionsForm(forms.Form):
|
|||||||
plottype = forms.ChoiceField(choices=plotchoices, initial='line',
|
plottype = forms.ChoiceField(choices=plotchoices, initial='line',
|
||||||
label='Chart Type')
|
label='Chart Type')
|
||||||
|
|
||||||
|
trendline = forms.BooleanField(initial=False, required=False,
|
||||||
|
label='Add Trend Line')
|
||||||
|
|
||||||
|
|
||||||
class ForceCurveOptionsForm(forms.Form):
|
class ForceCurveOptionsForm(forms.Form):
|
||||||
includereststrokes = forms.BooleanField(initial=False, required=False,
|
includereststrokes = forms.BooleanField(initial=False, required=False,
|
||||||
|
|||||||
@@ -4658,7 +4658,8 @@ def interactive_cum_flex_chart2(theworkouts, promember=0,
|
|||||||
xparam='spm',
|
xparam='spm',
|
||||||
yparam1='power',
|
yparam1='power',
|
||||||
yparam2='spm',
|
yparam2='spm',
|
||||||
workstrokesonly=False):
|
workstrokesonly=False,
|
||||||
|
trendline=False):
|
||||||
|
|
||||||
# datadf = dataprep.smalldataprep(theworkouts,xparam,yparam1,yparam2)
|
# datadf = dataprep.smalldataprep(theworkouts,xparam,yparam1,yparam2)
|
||||||
ids = [int(w.id) for w in theworkouts]
|
ids = [int(w.id) for w in theworkouts]
|
||||||
@@ -4747,6 +4748,15 @@ def interactive_cum_flex_chart2(theworkouts, promember=0,
|
|||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
datadf['yname2'] = axlabels[yparam1]
|
datadf['yname2'] = axlabels[yparam1]
|
||||||
|
|
||||||
|
def func(x, a, b):
|
||||||
|
return a*x+b
|
||||||
|
|
||||||
|
x1 = datadf['x1']
|
||||||
|
y1 = datadf['y1']
|
||||||
|
popt, pcov = optimize.curve_fit(func, x1, y1)
|
||||||
|
ytrend = func(x1, popt[0], popt[1])
|
||||||
|
datadf['ytrend'] = ytrend
|
||||||
|
|
||||||
source = ColumnDataSource(
|
source = ColumnDataSource(
|
||||||
datadf
|
datadf
|
||||||
)
|
)
|
||||||
@@ -4848,6 +4858,10 @@ def interactive_cum_flex_chart2(theworkouts, promember=0,
|
|||||||
minutes=["%M"]
|
minutes=["%M"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# trendline
|
||||||
|
if trendline:
|
||||||
|
plot.line('x1', 'ytrend', source=source2, legend_label=yparamname1+' (trend)')
|
||||||
|
|
||||||
if yparam2 != 'None':
|
if yparam2 != 'None':
|
||||||
yrange2 = Range1d(start=yaxminima[yparam2], end=yaxmaxima[yparam2])
|
yrange2 = Range1d(start=yaxminima[yparam2], end=yaxmaxima[yparam2])
|
||||||
plot.extra_y_ranges["yax2"] = yrange2
|
plot.extra_y_ranges["yax2"] = yrange2
|
||||||
@@ -4897,6 +4911,7 @@ def interactive_cum_flex_chart2(theworkouts, promember=0,
|
|||||||
var yname1 = data['yname1']
|
var yname1 = data['yname1']
|
||||||
var yname2 = data['yname2']
|
var yname2 = data['yname2']
|
||||||
var workoutid1 = data['workoutid']
|
var workoutid1 = data['workoutid']
|
||||||
|
var ytrend = data['ytrend']
|
||||||
|
|
||||||
var minspm = minspm.value
|
var minspm = minspm.value
|
||||||
var maxspm = maxspm.value
|
var maxspm = maxspm.value
|
||||||
@@ -4927,6 +4942,7 @@ def interactive_cum_flex_chart2(theworkouts, promember=0,
|
|||||||
data2['yname1'] = []
|
data2['yname1'] = []
|
||||||
data2['yname2'] = []
|
data2['yname2'] = []
|
||||||
data2['spm'] = []
|
data2['spm'] = []
|
||||||
|
data2['ytrend'] = []
|
||||||
|
|
||||||
for (var i=0; i<x1.length; i++) {
|
for (var i=0; i<x1.length; i++) {
|
||||||
if (spm1[i]>=minspm && spm1[i]<=maxspm) {
|
if (spm1[i]>=minspm && spm1[i]<=maxspm) {
|
||||||
@@ -4943,6 +4959,7 @@ def interactive_cum_flex_chart2(theworkouts, promember=0,
|
|||||||
data2['xname'].push(0)
|
data2['xname'].push(0)
|
||||||
data2['yname1'].push(0)
|
data2['yname1'].push(0)
|
||||||
data2['yname2'].push(0)
|
data2['yname2'].push(0)
|
||||||
|
data2['ytrend'].push(ytrend[i])
|
||||||
|
|
||||||
xm += x1[i]
|
xm += x1[i]
|
||||||
ym1 += y1[i]
|
ym1 += y1[i]
|
||||||
@@ -5392,6 +5409,7 @@ def interactive_flex_chart2(id, r, promember=0,
|
|||||||
yparam2='hr',
|
yparam2='hr',
|
||||||
plottype='line',
|
plottype='line',
|
||||||
workstrokesonly=False,
|
workstrokesonly=False,
|
||||||
|
trendline=False,
|
||||||
mode='rower'):
|
mode='rower'):
|
||||||
|
|
||||||
watermarkurl = "/static/img/logo7.png"
|
watermarkurl = "/static/img/logo7.png"
|
||||||
@@ -5557,6 +5575,15 @@ def interactive_flex_chart2(id, r, promember=0,
|
|||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
rowdata['yname2'] = rowdata['yname1']
|
rowdata['yname2'] = rowdata['yname1']
|
||||||
|
|
||||||
|
def func(x, a, b):
|
||||||
|
return a*x+b
|
||||||
|
|
||||||
|
x1 = rowdata['x1']
|
||||||
|
y1 = rowdata['y1']
|
||||||
|
popt, pcov = optimize.curve_fit(func, x1, y1)
|
||||||
|
ytrend = func(x1, popt[0], popt[1])
|
||||||
|
rowdata['ytrend'] = ytrend
|
||||||
|
|
||||||
# prepare data
|
# prepare data
|
||||||
source = ColumnDataSource(
|
source = ColumnDataSource(
|
||||||
rowdata
|
rowdata
|
||||||
@@ -5672,6 +5699,10 @@ def interactive_flex_chart2(id, r, promember=0,
|
|||||||
plot.line(xvals, yconstantpower, color="green",
|
plot.line(xvals, yconstantpower, color="green",
|
||||||
legend_label="Constant Power")
|
legend_label="Constant Power")
|
||||||
|
|
||||||
|
# trendline
|
||||||
|
if trendline:
|
||||||
|
plot.line('x1', 'ytrend', source=source2, legend_label=yaxlabel+' (trend)')
|
||||||
|
|
||||||
if plottype == 'line':
|
if plottype == 'line':
|
||||||
plot.line('x1', 'y1', source=source2, legend_label=yaxlabel)
|
plot.line('x1', 'y1', source=source2, legend_label=yaxlabel)
|
||||||
elif plottype == 'scatter': # pragma: no cover
|
elif plottype == 'scatter': # pragma: no cover
|
||||||
@@ -5806,6 +5837,7 @@ def interactive_flex_chart2(id, r, promember=0,
|
|||||||
var yname2 = data['yname2']
|
var yname2 = data['yname2']
|
||||||
var workoutid1 = data['workoutid']
|
var workoutid1 = data['workoutid']
|
||||||
var workoutstate1 = data['workoutstate']
|
var workoutstate1 = data['workoutstate']
|
||||||
|
var ytrend = data['ytrend']
|
||||||
|
|
||||||
var annotation = annotation.value
|
var annotation = annotation.value
|
||||||
var minspm = minspm.value
|
var minspm = minspm.value
|
||||||
@@ -5843,6 +5875,7 @@ def interactive_flex_chart2(id, r, promember=0,
|
|||||||
data2['xname'] = []
|
data2['xname'] = []
|
||||||
data2['yname1'] = []
|
data2['yname1'] = []
|
||||||
data2['yname2'] = []
|
data2['yname2'] = []
|
||||||
|
data2['ytrend'] = []
|
||||||
|
|
||||||
|
|
||||||
for (var i=0; i<x1.length; i++) {
|
for (var i=0; i<x1.length; i++) {
|
||||||
@@ -5866,6 +5899,7 @@ def interactive_flex_chart2(id, r, promember=0,
|
|||||||
data2['xname'].push(0)
|
data2['xname'].push(0)
|
||||||
data2['yname1'].push(0)
|
data2['yname1'].push(0)
|
||||||
data2['yname2'].push(0)
|
data2['yname2'].push(0)
|
||||||
|
data2['ytrend'].push(ytrend[i])
|
||||||
|
|
||||||
|
|
||||||
xm += x1[i]
|
xm += x1[i]
|
||||||
|
|||||||
@@ -3028,8 +3028,8 @@ def handle_nk_async_workout(alldata, userid, nktoken, nkid, delaysec, defaulttim
|
|||||||
jsonData = response.json()
|
jsonData = response.json()
|
||||||
strokeData = jsonData[str(nkid)]
|
strokeData = jsonData[str(nkid)]
|
||||||
|
|
||||||
dologging('nklog.log', json.dumps(data))
|
#dologging('nklog.log', json.dumps(data))
|
||||||
dologging('nklog.log', json.dumps(strokeData))
|
#dologging('nklog.log', json.dumps(strokeData))
|
||||||
|
|
||||||
seatNumber = 1
|
seatNumber = 1
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -89,6 +89,7 @@
|
|||||||
var plottype = $("#id_plottype").parent().parent();
|
var plottype = $("#id_plottype").parent().parent();
|
||||||
|
|
||||||
var reststrokes = $("#id_includereststrokes").parent().parent();
|
var reststrokes = $("#id_includereststrokes").parent().parent();
|
||||||
|
var trendline = $("#id_trendline").parent().parent();
|
||||||
var piece = $("#id_piece").parent().parent();
|
var piece = $("#id_piece").parent().parent();
|
||||||
var cpfit = $("#id_cpfit").parent().parent();
|
var cpfit = $("#id_cpfit").parent().parent();
|
||||||
var cpoverlay = $("#id_cpoverlay").parent().parent();
|
var cpoverlay = $("#id_cpoverlay").parent().parent();
|
||||||
@@ -116,6 +117,7 @@
|
|||||||
cpfit.hide();
|
cpfit.hide();
|
||||||
cpoverlay.hide();
|
cpoverlay.hide();
|
||||||
piece.hide();
|
piece.hide();
|
||||||
|
trendline.hide();
|
||||||
|
|
||||||
if (functionfield.val() == 'boxplot') {
|
if (functionfield.val() == 'boxplot') {
|
||||||
plotfield.show();
|
plotfield.show();
|
||||||
@@ -140,6 +142,7 @@
|
|||||||
xaxis.show();
|
xaxis.show();
|
||||||
yaxis1.show();
|
yaxis1.show();
|
||||||
yaxis2.show();
|
yaxis2.show();
|
||||||
|
trendline.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (functionfield.val() == 'stats') {
|
if (functionfield.val() == 'stats') {
|
||||||
@@ -181,6 +184,7 @@
|
|||||||
palette.hide();
|
palette.hide();
|
||||||
binsize.hide();
|
binsize.hide();
|
||||||
errorbars.hide();
|
errorbars.hide();
|
||||||
|
trendline.hide();
|
||||||
xaxis.hide();
|
xaxis.hide();
|
||||||
yaxis1.hide();
|
yaxis1.hide();
|
||||||
yaxis2.hide();
|
yaxis2.hide();
|
||||||
@@ -201,6 +205,7 @@
|
|||||||
groupby.hide();
|
groupby.hide();
|
||||||
palette.hide();
|
palette.hide();
|
||||||
binsize.hide();
|
binsize.hide();
|
||||||
|
trendline.hide();
|
||||||
errorbars.hide();
|
errorbars.hide();
|
||||||
xaxis.hide();
|
xaxis.hide();
|
||||||
yaxis1.hide();
|
yaxis1.hide();
|
||||||
@@ -222,6 +227,7 @@
|
|||||||
spmmin.show();
|
spmmin.show();
|
||||||
spmmax.show();
|
spmmax.show();
|
||||||
workmin.show();
|
workmin.show();
|
||||||
|
trendline.hide();
|
||||||
workmax.show();
|
workmax.show();
|
||||||
plotfield.hide();
|
plotfield.hide();
|
||||||
xaxis.hide();
|
xaxis.hide();
|
||||||
@@ -242,6 +248,7 @@
|
|||||||
y_param.hide();
|
y_param.hide();
|
||||||
groupby.hide();
|
groupby.hide();
|
||||||
spmmin.hide();
|
spmmin.hide();
|
||||||
|
trendline.show();
|
||||||
spmmax.hide();
|
spmmax.hide();
|
||||||
workmin.hide();
|
workmin.hide();
|
||||||
workmax.hide();
|
workmax.hide();
|
||||||
@@ -267,6 +274,7 @@
|
|||||||
binsize.hide();
|
binsize.hide();
|
||||||
errorbars.hide();
|
errorbars.hide();
|
||||||
plottype.hide();
|
plottype.hide();
|
||||||
|
trendline.hide();
|
||||||
reststrokes.show();
|
reststrokes.show();
|
||||||
cpfit.hide();
|
cpfit.hide();
|
||||||
cpoverlay.hide();
|
cpoverlay.hide();
|
||||||
@@ -285,6 +293,7 @@
|
|||||||
workmax.hide();
|
workmax.hide();
|
||||||
plotfield.hide();
|
plotfield.hide();
|
||||||
palette.hide();
|
palette.hide();
|
||||||
|
trendline.hide();
|
||||||
binsize.hide();
|
binsize.hide();
|
||||||
plottype.show();
|
plottype.show();
|
||||||
errorbars.hide();
|
errorbars.hide();
|
||||||
@@ -303,6 +312,7 @@
|
|||||||
workmax.hide();
|
workmax.hide();
|
||||||
x_param.hide();
|
x_param.hide();
|
||||||
y_param.hide();
|
y_param.hide();
|
||||||
|
trendline.hide();
|
||||||
groupby.hide();
|
groupby.hide();
|
||||||
palette.hide();
|
palette.hide();
|
||||||
binsize.hide();
|
binsize.hide();
|
||||||
|
|||||||
@@ -805,6 +805,7 @@ class WorkoutStatsTestNew(TestCase):
|
|||||||
'startdate':startdate,
|
'startdate':startdate,
|
||||||
'enddate':enddate,
|
'enddate':enddate,
|
||||||
'plottype':'scatter',
|
'plottype':'scatter',
|
||||||
|
'trendline':True,
|
||||||
'spmmin':15,
|
'spmmin':15,
|
||||||
'spmmax':55,
|
'spmmax':55,
|
||||||
'workmin':0,
|
'workmin':0,
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ defaultoptions = {
|
|||||||
'waterboattype': mytypes.waterboattype,
|
'waterboattype': mytypes.waterboattype,
|
||||||
'function': 'boxplot',
|
'function': 'boxplot',
|
||||||
'ranking': False,
|
'ranking': False,
|
||||||
|
'trendline': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -307,6 +308,7 @@ def trendflexdata(workouts, options, userid=0):
|
|||||||
ids = options['ids']
|
ids = options['ids']
|
||||||
workstrokesonly = not includereststrokes
|
workstrokesonly = not includereststrokes
|
||||||
|
|
||||||
|
|
||||||
fieldlist, fielddict = dataprep.getstatsfields()
|
fieldlist, fielddict = dataprep.getstatsfields()
|
||||||
fieldlist = [xparam, yparam, groupby,
|
fieldlist = [xparam, yparam, groupby,
|
||||||
'workoutid', 'spm', 'driveenergy',
|
'workoutid', 'spm', 'driveenergy',
|
||||||
@@ -477,6 +479,7 @@ def flexalldata(workouts, options):
|
|||||||
xparam = options['xaxis']
|
xparam = options['xaxis']
|
||||||
yparam1 = options['yaxis1']
|
yparam1 = options['yaxis1']
|
||||||
yparam2 = options['yaxis2']
|
yparam2 = options['yaxis2']
|
||||||
|
trendline = options['trendline']
|
||||||
promember = True
|
promember = True
|
||||||
|
|
||||||
workstrokesonly = not includereststrokes
|
workstrokesonly = not includereststrokes
|
||||||
@@ -486,6 +489,7 @@ def flexalldata(workouts, options):
|
|||||||
yparam2=yparam2,
|
yparam2=yparam2,
|
||||||
promember=promember,
|
promember=promember,
|
||||||
workstrokesonly=workstrokesonly,
|
workstrokesonly=workstrokesonly,
|
||||||
|
trendline=trendline,
|
||||||
)
|
)
|
||||||
script = res[0]
|
script = res[0]
|
||||||
div = res[1]
|
div = res[1]
|
||||||
|
|||||||
@@ -3760,6 +3760,11 @@ def workout_flexchart3_view(request, *args, **kwargs):
|
|||||||
else:
|
else:
|
||||||
plottype = 'line'
|
plottype = 'line'
|
||||||
|
|
||||||
|
if 'trendline' in kwargs: # pragma: no cover
|
||||||
|
trendline = kwargs['trendline']
|
||||||
|
else:
|
||||||
|
trendline = False
|
||||||
|
|
||||||
if 'workstrokesonly' in kwargs: # pragma: no cover
|
if 'workstrokesonly' in kwargs: # pragma: no cover
|
||||||
workstrokesonly = kwargs['workstrokesonly']
|
workstrokesonly = kwargs['workstrokesonly']
|
||||||
else:
|
else:
|
||||||
@@ -3790,6 +3795,7 @@ def workout_flexchart3_view(request, *args, **kwargs):
|
|||||||
cd = flexoptionsform.cleaned_data
|
cd = flexoptionsform.cleaned_data
|
||||||
includereststrokes = cd['includereststrokes']
|
includereststrokes = cd['includereststrokes']
|
||||||
plottype = cd['plottype']
|
plottype = cd['plottype']
|
||||||
|
trendline = cd['trendline']
|
||||||
|
|
||||||
workstrokesonly = not includereststrokes
|
workstrokesonly = not includereststrokes
|
||||||
|
|
||||||
@@ -3832,7 +3838,9 @@ def workout_flexchart3_view(request, *args, **kwargs):
|
|||||||
xparam=xparam, yparam1=yparam1,
|
xparam=xparam, yparam1=yparam1,
|
||||||
yparam2=yparam2,
|
yparam2=yparam2,
|
||||||
promember=promember, plottype=plottype,
|
promember=promember, plottype=plottype,
|
||||||
workstrokesonly=workstrokesonly, mode=row.workouttype
|
workstrokesonly=workstrokesonly,
|
||||||
|
trendline=trendline,
|
||||||
|
mode=row.workouttype
|
||||||
)
|
)
|
||||||
|
|
||||||
axchoicesbasic = {ax[0]: ax[1] for ax in axes if ax[4] == 'basic'}
|
axchoicesbasic = {ax[0]: ax[1] for ax in axes if ax[4] == 'basic'}
|
||||||
@@ -3876,7 +3884,8 @@ def workout_flexchart3_view(request, *args, **kwargs):
|
|||||||
|
|
||||||
initial = {
|
initial = {
|
||||||
'includereststrokes': not workstrokesonly,
|
'includereststrokes': not workstrokesonly,
|
||||||
'plottype': plottype
|
'plottype': plottype,
|
||||||
|
'trendline': trendline,
|
||||||
}
|
}
|
||||||
|
|
||||||
flexoptionsform = FlexOptionsForm(initial=initial)
|
flexoptionsform = FlexOptionsForm(initial=initial)
|
||||||
|
|||||||
Reference in New Issue
Block a user