diff --git a/rowers/forms.py b/rowers/forms.py index 3bfbe8ce..6d387abb 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -1108,6 +1108,17 @@ class AnalysisChoiceForm(forms.Form): required=False, label='Include Rest Strokes') + cpfitchoices = ( + ('data','Fit to Selected Workouts'), + ('automatic','Critical Power Rolling Data') + ) + + cpfit = forms.ChoiceField(choices=cpfitchoices, + label = 'Model Fit',initial='data',required=False) + + piece = forms.IntegerField(initial=4,label='Ranking Piece (minutes)', + required=False) + class BoxPlotChoiceForm(forms.Form): yparam = forms.ChoiceField(choices=parchoices,initial='spm', label='Metric') diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 56deef4b..3f78a6f4 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -2881,7 +2881,7 @@ def interactive_agegroupcpchart(age,normalized=False): return script,div -def interactive_otwcpchart(powerdf,promember=0,rowername=""): +def interactive_otwcpchart(powerdf,promember=0,rowername="",r=None,cpfit='data'): powerdf = powerdf[~(powerdf == 0).any(axis=1)] # plot tools if (promember==1): @@ -2906,7 +2906,13 @@ def interactive_otwcpchart(powerdf,promember=0,rowername=""): thesecs = powerdf['Delta'] theavpower = powerdf['CP'] + p1,fitt,fitpower,ratio = datautils.cpfit(powerdf) + if cpfit == 'automatic' and r is not None: + p1 = [r.p0,r.p1,r.p2,r.p3] + ratio = r.cpratio + fitfunc = lambda pars,x: abs(pars[0])/(1+(x/abs(pars[2]))) + abs(pars[1])/(1+(x/abs(pars[3]))) + fitpower = fitfunc(p1,fitt) message = "" #if len(fitpower[fitpower<0]) > 0: diff --git a/rowers/templates/otwcp.html b/rowers/templates/otwcp.html new file mode 100644 index 00000000..798ba395 --- /dev/null +++ b/rowers/templates/otwcp.html @@ -0,0 +1,20 @@ + + {{ the_div|safe }} +
+
| Duration | +Power Estimate 1 | +Power Estimate 2 | +
|---|---|---|
| {{ duration }} | +{{ power }} | +{{ upper }} | +
You can use the date and search forms to search through all @@ -327,7 +354,7 @@
{{ searchform }}
{% if workouts %} diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py index aa8cce9d..d0ea82e2 100644 --- a/rowers/views/analysisviews.py +++ b/rowers/views/analysisviews.py @@ -274,6 +274,8 @@ def trendflexdata(workouts, options,userid=0): workmin = options['workmin'] workmax = options['workmax'] ploterrorbars = options['ploterrorbars'] + cpfit = options['cpfit'] + piece = options['piece'] ids = options['ids'] workstrokesonly = not includereststrokes @@ -502,7 +504,7 @@ def histodata(workouts, options): def cpdata(workouts, options): userid = options['userid'] - + cpfit = options['cpfit'] u = User.objects.get(id=userid) r = u.rower @@ -527,17 +529,18 @@ def cpdata(workouts, options): rowername = r.user.first_name+" "+r.user.last_name if len(powerdf) !=0 : - res = interactive_otwcpchart(powerdf,promember=True,rowername=rowername) + res = interactive_otwcpchart(powerdf,promember=True,rowername=rowername,r=r, + cpfit=cpfit) script = res[0] div = res[1] p1 = res[2] ratio = res[3] - r.p0 = p1[0] - r.p1 = p1[1] - r.p2 = p1[2] - r.p3 = p1[3] - r.cpratio = ratio - r.save() + #r.p0 = p1[0] + #r.p1 = p1[1] + #r.p2 = p1[2] + #r.p3 = p1[3] + #r.cpratio = ratio + #r.save() paulslope = 1 paulintercept = 1 message = res[4] @@ -547,12 +550,57 @@ def cpdata(workouts, options): paulslope = 1 paulintercept = 1 p1 = [1,1,1,1] + ratio = 1 message = "" scripta = script.split('\n')[2:-1] script = ''.join(scripta) - return (script,div) + minutes = options['piece'] + if minutes != 0: + hourvalue,tvalue = divmod(minutes,60) + hourvalue = int(hourvalue) + minutevalue = int(tvalue) + tvalue = int(60*(tvalue-minutevalue)) + if hourvalue >= 24: + hourvalue = 23 + pieceduration = datetime.time( + minute = minutevalue, + hour = hourvalue, + second = tvalue, + ) + pieceseconds = 2600.*pieceduration.hour+60.*pieceduration.minute+pieceduration.second + # CP model + pwr = p1[0]/(1+pieceseconds/p1[2]) + pwr += p1[1]/(1+pieceseconds/p1[3]) + + if pwr <= 0: + pwr = 50. + + if not np.isnan(pwr): + try: + pwr2 = pwr*ratio + except: + pwr2 = pwr + + duration = timedeltaconv(pieceseconds) + power = int(pwr) + upper = int(pwr2) + else: + duration = timedeltaconv(0) + power = 0 + upper = 0 + + htmly = env.get_template('otwcp.html') + html_content = htmly.render({ + 'script':script, + 'the_div':div, + 'duration':duration, + 'power':power, + 'upper':upper, + }) + + return (script,html_content) def statsdata(workouts, options): includereststrokes = options['includereststrokes']