diff --git a/rowers/forms.py b/rowers/forms.py index fae9c06e..8610dab5 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -1373,6 +1373,9 @@ class AnalysisChoiceForm(forms.Form): required=False, label='Include Rest Strokes') + trendline = forms.BooleanField(initial=False, required=False, + label='Trend Line') + def __init__(self, *args, **kwargs): super(AnalysisChoiceForm, self).__init__(*args, **kwargs) @@ -1808,6 +1811,9 @@ class FlexOptionsForm(forms.Form): plottype = forms.ChoiceField(choices=plotchoices, initial='line', label='Chart Type') + trendline = forms.BooleanField(initial=False, required=False, + label='Add Trend Line') + class ForceCurveOptionsForm(forms.Form): includereststrokes = forms.BooleanField(initial=False, required=False, diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index d0d87fd6..faad59d2 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -4658,7 +4658,8 @@ def interactive_cum_flex_chart2(theworkouts, promember=0, xparam='spm', yparam1='power', yparam2='spm', - workstrokesonly=False): + workstrokesonly=False, + trendline=False): # datadf = dataprep.smalldataprep(theworkouts,xparam,yparam1,yparam2) ids = [int(w.id) for w in theworkouts] @@ -4747,6 +4748,15 @@ def interactive_cum_flex_chart2(theworkouts, promember=0, else: # pragma: no cover 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( datadf ) @@ -4848,6 +4858,10 @@ def interactive_cum_flex_chart2(theworkouts, promember=0, minutes=["%M"] ) + # trendline + if trendline: + plot.line('x1', 'ytrend', source=source2, legend_label=yparamname1+' (trend)') + if yparam2 != 'None': yrange2 = Range1d(start=yaxminima[yparam2], end=yaxmaxima[yparam2]) plot.extra_y_ranges["yax2"] = yrange2 @@ -4897,6 +4911,7 @@ def interactive_cum_flex_chart2(theworkouts, promember=0, var yname1 = data['yname1'] var yname2 = data['yname2'] var workoutid1 = data['workoutid'] + var ytrend = data['ytrend'] var minspm = minspm.value var maxspm = maxspm.value @@ -4927,6 +4942,7 @@ def interactive_cum_flex_chart2(theworkouts, promember=0, data2['yname1'] = [] data2['yname2'] = [] data2['spm'] = [] + data2['ytrend'] = [] for (var i=0; i=minspm && spm1[i]<=maxspm) { @@ -4943,6 +4959,7 @@ def interactive_cum_flex_chart2(theworkouts, promember=0, data2['xname'].push(0) data2['yname1'].push(0) data2['yname2'].push(0) + data2['ytrend'].push(ytrend[i]) xm += x1[i] ym1 += y1[i] @@ -5392,6 +5409,7 @@ def interactive_flex_chart2(id, r, promember=0, yparam2='hr', plottype='line', workstrokesonly=False, + trendline=False, mode='rower'): watermarkurl = "/static/img/logo7.png" @@ -5557,6 +5575,15 @@ def interactive_flex_chart2(id, r, promember=0, else: # pragma: no cover 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 source = ColumnDataSource( rowdata @@ -5672,6 +5699,10 @@ def interactive_flex_chart2(id, r, promember=0, plot.line(xvals, yconstantpower, color="green", legend_label="Constant Power") + # trendline + if trendline: + plot.line('x1', 'ytrend', source=source2, legend_label=yaxlabel+' (trend)') + if plottype == 'line': plot.line('x1', 'y1', source=source2, legend_label=yaxlabel) elif plottype == 'scatter': # pragma: no cover @@ -5806,6 +5837,7 @@ def interactive_flex_chart2(id, r, promember=0, var yname2 = data['yname2'] var workoutid1 = data['workoutid'] var workoutstate1 = data['workoutstate'] + var ytrend = data['ytrend'] var annotation = annotation.value var minspm = minspm.value @@ -5843,6 +5875,7 @@ def interactive_flex_chart2(id, r, promember=0, data2['xname'] = [] data2['yname1'] = [] data2['yname2'] = [] + data2['ytrend'] = [] for (var i=0; i