diff --git a/rowers/dataprep.py b/rowers/dataprep.py
index ef153533..164e50b9 100644
--- a/rowers/dataprep.py
+++ b/rowers/dataprep.py
@@ -2564,9 +2564,11 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True,
if id != 0:
data['workoutid'] = id
data.fillna(0,inplace=True)
- data = data.astype(
- dtype=dtypes,
- )
+ for k, v in dtypes.items():
+ try:
+ data[k] = data[k].astype(v)
+ except KeyError:
+ pass
filename = 'media/strokedata_{id}.parquet.gz'.format(id=id)
diff --git a/rowers/dataprepnodjango.py b/rowers/dataprepnodjango.py
index cdf2580a..bdd1f162 100644
--- a/rowers/dataprepnodjango.py
+++ b/rowers/dataprepnodjango.py
@@ -1254,7 +1254,13 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True,
# write data if id given
if id != 0:
data['workoutid'] = id
- data = data.astype(dtype=dtypes)
+ data.fillna(0,inplace=True)
+ for k, v in dtypes.items():
+ try:
+ data[k] = data[k].astype(v)
+ except KeyError:
+ pass
+
filename = 'media/strokedata_{id}.parquet.gz'.format(id=id)
df = dd.from_pandas(data,npartitions=1)
df.to_parquet(filename,engine='fastparquet',compression='GZIP')
diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py
index 9cb21f11..d76f3a57 100644
--- a/rowers/views/analysisviews.py
+++ b/rowers/views/analysisviews.py
@@ -48,7 +48,7 @@ def analysis_new(request,userid=0,function='boxplot',teamid=0):
options = request.session['options']
else:
options=defaultoptions
-
+
options['userid'] = userid
try:
workouttypes = options['workouttypes']
@@ -62,13 +62,13 @@ def analysis_new(request,userid=0,function='boxplot',teamid=0):
modalities = [m[0] for m in mytypes.workouttypes_ordered.items()]
modality = 'all'
-
-
+
+
try:
rankingonly = options['rankingonly']
except KeyError:
rankingonly = False
-
+
try:
includereststrokes = options['includereststrokes']
except KeyError:
@@ -78,7 +78,7 @@ def analysis_new(request,userid=0,function='boxplot',teamid=0):
startdate = iso8601.parse_date(request.session['startdate'])
else:
startdate=timezone.now()-datetime.timedelta(days=42)
-
+
if function not in [c[0] for c in analysischoices]:
function = 'boxplot'
@@ -105,7 +105,7 @@ def analysis_new(request,userid=0,function='boxplot',teamid=0):
if optionsform.is_valid():
for key, value in optionsform.cleaned_data.items():
options[key] = value
-
+
modality = optionsform.cleaned_data['modality']
waterboattype = optionsform.cleaned_data['waterboattype']
if modality == 'all':
@@ -120,7 +120,7 @@ def analysis_new(request,userid=0,function='boxplot',teamid=0):
rankingonly = optionsform.cleaned_data['rankingonly']
else:
rankingonly = False
-
+
options['modalities'] = modalities
options['waterboattype'] = waterboattype
@@ -128,8 +128,8 @@ def analysis_new(request,userid=0,function='boxplot',teamid=0):
if chartform.is_valid():
for key, value in chartform.cleaned_data.items():
options[key] = value
-
-
+
+
form = WorkoutMultipleCompareForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
@@ -192,10 +192,10 @@ def analysis_new(request,userid=0,function='boxplot',teamid=0):
"-date", "-starttime"
).exclude(boattype__in=negtypes)
-
+
if rankingonly:
workouts = workouts.exclude(rankingpiece=False)
-
+
query = request.GET.get('q')
if query:
query_list = query.split()
@@ -215,7 +215,7 @@ def analysis_new(request,userid=0,function='boxplot',teamid=0):
selectedworkouts = Workout.objects.none()
else:
selectedworkouts = Workout.objects.filter(id__in=ids)
-
+
form.fields["workouts"].queryset = workouts | selectedworkouts
optionsform = AnalysisOptionsForm(initial={
@@ -223,9 +223,9 @@ def analysis_new(request,userid=0,function='boxplot',teamid=0):
'waterboattype':waterboattype,
'rankingonly':rankingonly,
})
-
-
+
+
startdatestring = startdate.strftime('%Y-%m-%d')
enddatestring = enddate.strftime('%Y-%m-%d')
request.session['startdate'] = startdatestring
@@ -275,16 +275,16 @@ def trendflexdata(workouts, options,userid=0):
ploterrorbars = options['ploterrorbars']
ids = options['ids']
workstrokesonly = not includereststrokes
-
+
labeldict = {
int(w.id): w.__str__() for w in workouts
}
-
+
fieldlist,fielddict = dataprep.getstatsfields()
fieldlist = [xparam,yparam,groupby,
'workoutid','spm','driveenergy',
'workoutstate']
-
+
# prepare data frame
datadf,extracols = dataprep.read_cols_df_sql(ids,fieldlist)
@@ -335,9 +335,9 @@ def trendflexdata(workouts, options,userid=0):
)
groups = datadf.groupby(pd.cut(datadf['days ago'], bins,
labels=False))
-
- xvalues = groups.mean()[xparam]
+
+ xvalues = groups.mean()[xparam]
yvalues = groups.mean()[yparam]
xerror = groups.std()[xparam]
yerror = groups.std()[yparam]
@@ -363,7 +363,7 @@ def trendflexdata(workouts, options,userid=0):
return HttpResponseRedirect(url)
else:
groupsize = 30.*np.sqrt(groupsize/float(groupsize.max()))
-
+
df = pd.DataFrame({
xparam:xvalues,
yparam:yvalues,
@@ -377,14 +377,14 @@ def trendflexdata(workouts, options,userid=0):
if yparam == 'pace':
df['y'] = dataprep.paceformatsecs(df['y']/1.0e3)
-
+
aantal = len(df)
-
+
if groupby != 'date':
try:
df['groupval'] = groups.mean()[groupby]
df['groupval'].loc[mask] = np.nan
-
+
groupcols = df['groupval']
except ValueError:
df['groupval'] = groups.mean()[groupby].fillna(value=0)
@@ -393,7 +393,7 @@ def trendflexdata(workouts, options,userid=0):
except KeyError:
messages.error(request,'Data selection error')
url = reverse(user_multiflex_select)
- return HttpResponseRedirect(url)
+ return HttpResponseRedirect(url)
else:
try:
dates = groups.min()[groupby]
@@ -405,16 +405,16 @@ def trendflexdata(workouts, options,userid=0):
except AttributeError:
df['groupval'] = groups.mean()['days ago'].fillna(value=0)
groupcols = 100.*np.arange(aantal)/float(aantal)
-
-
+
+
groupcols = (groupcols-groupcols.min())/(groupcols.max()-groupcols.min())
if aantal == 1:
groupcols = np.array([1.])
-
+
colors = range_to_color_hex(groupcols,palette=palette)
-
+
df['color'] = colors
clegendx = np.arange(0,1.2,.2)
@@ -425,7 +425,7 @@ def trendflexdata(workouts, options,userid=0):
clegendy = df.index.min()+clegendx*(df.index.max()-df.index.min())
-
+
colorlegend = zip(range(6),clegendy,legcolors)
@@ -434,9 +434,9 @@ def trendflexdata(workouts, options,userid=0):
else:
u = User.objects.get(id=userid)
extratitle = ' '+u.first_name+' '+u.last_name
-
-
+
+
script,div = interactive_multiflex(df,xparam,yparam,
groupby,
extratitle=extratitle,
@@ -445,7 +445,7 @@ def trendflexdata(workouts, options,userid=0):
colorlegend=colorlegend,
spmmin=spmmin,spmmax=spmmax,
workmin=workmin,workmax=workmax)
-
+
scripta= script.split('\n')[2:-1]
script = ''.join(scripta)
@@ -471,9 +471,9 @@ def flexalldata(workouts, options):
scripta = script.split('\n')[2:-1]
script = ''.join(scripta)
-
+
return(script,div)
-
+
def histodata(workouts, options):
includereststrokes = options['includereststrokes']
plotfield = options['plotfield']
@@ -482,13 +482,13 @@ def histodata(workouts, options):
spmmax = options['spmmax']
workmin = options['workmin']
workmax = options['workmax']
-
+
workstrokesonly = not includereststrokes
script, div = interactive_histoall(workouts,plotfield,includereststrokes,
spmmin=spmmin,spmmax=spmmax,workmin=workmin,workmax=workmax)
-
+
scripta = script.split('\n')[2:-1]
script = ''.join(scripta)
@@ -528,17 +528,20 @@ def statsdata(workouts, options):
for field,verbosename in fielddict.items():
- thedict = {
- 'mean':datadf[field].mean(),
- 'min': datadf[field].min(),
- 'std': datadf[field].std(),
- 'max': datadf[field].max(),
- 'median': datadf[field].median(),
- 'firstq':datadf[field].quantile(q=0.25),
- 'thirdq':datadf[field].quantile(q=0.75),
- 'verbosename':verbosename,
- }
- stats[field] = thedict
+ try:
+ thedict = {
+ 'mean':datadf[field].mean(),
+ 'min': datadf[field].min(),
+ 'std': datadf[field].std(),
+ 'max': datadf[field].max(),
+ 'median': datadf[field].median(),
+ 'firstq':datadf[field].quantile(q=0.25),
+ 'thirdq':datadf[field].quantile(q=0.75),
+ 'verbosename':verbosename,
+ }
+ stats[field] = thedict
+ except KeyError:
+ pass
# Create a dict with correlation values
cor = datadf.corr(method='spearman')
@@ -558,7 +561,7 @@ def statsdata(workouts, options):
'stats':stats,
'cordict':cordict,
}
-
+
htmly = env.get_template('statsdiv.html')
html_content = htmly.render(context)
@@ -591,7 +594,7 @@ def comparisondata(workouts,options):
script = ''.join(scripta)
return(script,div)
-
+
def boxplotdata(workouts,options):
@@ -609,25 +612,25 @@ def boxplotdata(workouts,options):
labeldict = {
int(w.id): w.__str__() for w in workouts
}
-
-
+
+
datemapping = {
w.id:w.date for w in workouts
}
-
-
+
+
fieldlist,fielddict = dataprep.getstatsfields()
fieldlist = [plotfield,'workoutid','spm','driveenergy',
'workoutstate']
ids = [w.id for w in workouts]
-
+
# prepare data frame
datadf,extracols = dataprep.read_cols_df_sql(ids,fieldlist)
-
+
datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly)
datadf = dataprep.filter_df(datadf,'spm',spmmin,
@@ -651,9 +654,9 @@ def boxplotdata(workouts,options):
else:
u = User.objects.get(id=userid)
extratitle = ' '+u.first_name+' '+u.last_name
-
-
+
+
script,div = interactive_boxchart(datadf,plotfield,
extratitle=extratitle,
spmmin=spmmin,spmmax=spmmax,workmin=workmin,workmax=workmax)
@@ -670,7 +673,7 @@ def analysis_view_data(request,userid=0):
if not request.is_ajax():
url = reverse('analysis_new')
return HttpResponseRedirect(url)
-
+
if 'options' in request.session:
options = request.session['options']
else:
@@ -712,14 +715,14 @@ def analysis_view_data(request,userid=0):
else:
script = ''
div = 'Unknown analysis functions'
-
+
return JSONResponse({
"script":script,
"div":div,
})
-
+
# Histogram for a date/time range
@user_passes_test(ispromember,login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher",
@@ -745,13 +748,13 @@ def histo(request,theuser=0,
histoparam = request.session['histoparam']
else:
histoparam = 'power'
-
+
if 'waterboattype' in request.session:
waterboattype = request.session['waterboattype']
else:
waterboattype = mytypes.waterboattype
-
+
if 'rankingonly' in request.session:
rankingonly = request.session['rankingonly']
else:
@@ -772,7 +775,7 @@ def histo(request,theuser=0,
rankingonly = options['rankingonly']
except KeyError:
rankingonly = False
-
+
try:
includereststrokes = options['includereststrokes']
except KeyError:
@@ -795,9 +798,9 @@ def histo(request,theuser=0,
enddate = startdate
startdate = s
-
+
# get all indoor rows of in date range
-
+
# process form
if request.method == 'POST':
form = DateRangeForm(request.POST)
@@ -824,7 +827,7 @@ def histo(request,theuser=0,
if modality != 'water':
waterboattype = [b[0] for b in mytypes.boattypes]
-
+
request.session['modalities'] = modalities
request.session['waterboattype'] = waterboattype
request.session['rankingonly'] = rankingonly
@@ -869,9 +872,9 @@ def histo(request,theuser=0,
js_resources = ''
css_resources = ''
-
-
-
+
+
+
options = {
'modality': modality,
'theuser': theuser.id,
@@ -891,7 +894,7 @@ def histo(request,theuser=0,
result = request.user.is_authenticated and ispromember(request.user)
if result:
promember = 1
-
+
request.session['options'] = options
@@ -945,8 +948,8 @@ def cum_flex_data(
if 'options' in request.session:
options = request.session['options']
-
- modality = keyvalue_get_default('modality',options,def_options)
+
+ modality = keyvalue_get_default('modality',options,def_options)
rankingonly = keyvalue_get_default('rankingonly',options,def_options)
includereststrokes = keyvalue_get_default('includereststrokes',options,def_options)
waterboattype = keyvalue_get_default('waterboattype',options,def_options)
@@ -963,7 +966,7 @@ def cum_flex_data(
modalities = [m[0] for m in mytypes.workouttypes]
else:
modalities = [modality]
-
+
try:
startdate = iso8601.parse_date(startdatestring)
except ParseError:
@@ -1003,7 +1006,7 @@ def cum_flex_data(
startdatetime__gte=startdate,
startdatetime__lte=enddate,
rankingpiece__in=rankingpiece)
-
+
if allworkouts:
res = interactive_cum_flex_chart2(allworkouts,xparam=xparam,
yparam1=yparam1,
@@ -1019,7 +1022,7 @@ def cum_flex_data(
scripta = script.split('\n')[2:-1]
script = ''.join(scripta)
-
+
data = {
"script":script,
"div":div,
@@ -1045,11 +1048,11 @@ def histo_data(
def_options = options
-
+
if 'options' in request.session:
options = request.session['options']
- modality = keyvalue_get_default('modality',options,def_options)
+ modality = keyvalue_get_default('modality',options,def_options)
rankingonly = keyvalue_get_default('rankingonly',options,def_options)
includereststrokes = keyvalue_get_default('includereststrokes',options,def_options)
waterboattype = keyvalue_get_default('waterboattype',options,def_options)
@@ -1063,7 +1066,7 @@ def histo_data(
modalities = [m[0] for m in mytypes.workouttypes]
else:
modalities = [modality]
-
+
try:
startdate = iso8601.parse_date(startdatestring)
except ParseError:
@@ -1096,14 +1099,14 @@ def histo_data(
rankingpiece = [True,]
else:
rankingpiece = [True,False]
-
+
allworkouts = Workout.objects.filter(user=r2,
workouttype__in=modalities,
boattype__in=waterboattype,
startdatetime__gte=startdate,
startdatetime__lte=enddate,
rankingpiece__in=rankingpiece)
-
+
if allworkouts:
res = interactive_histoall(allworkouts,histoparam,includereststrokes)
script = res[0]
@@ -1114,7 +1117,7 @@ def histo_data(
scripta = script.split('\n')[2:-1]
script = ''.join(scripta)
-
+
data = {
"script":script,
"div":div,
@@ -1145,13 +1148,13 @@ def cum_flex(request,theuser=0,
r = getrequestrower(request,userid=theuser)
theuser = r.user
-
+
if 'waterboattype' in request.session:
waterboattype = request.session['waterboattype']
else:
waterboattype = mytypes.waterboattype
-
+
if 'rankingonly' in request.session:
rankingonly = request.session['rankingonly']
else:
@@ -1172,7 +1175,7 @@ def cum_flex(request,theuser=0,
rankingonly = options['rankingonly']
except KeyError:
rankingonly = False
-
+
try:
includereststrokes = options['includereststrokes']
except KeyError:
@@ -1195,9 +1198,9 @@ def cum_flex(request,theuser=0,
enddate = startdate
startdate = s
-
+
# get all indoor rows of in date range
-
+
# process form
if request.method == 'POST':
form = DateRangeForm(request.POST)
@@ -1224,7 +1227,7 @@ def cum_flex(request,theuser=0,
if modality != 'water':
waterboattype = [b[0] for b in mytypes.boattypes]
-
+
request.session['modalities'] = modalities
request.session['waterboattype'] = waterboattype
request.session['rankingonly'] = rankingonly
@@ -1270,9 +1273,9 @@ def cum_flex(request,theuser=0,
js_resources = ''
css_resources = ''
-
-
-
+
+
+
options = {
'xparam': xparam,
'yparam1': yparam1,
@@ -1294,11 +1297,11 @@ def cum_flex(request,theuser=0,
result = request.user.is_authenticated and ispromember(request.user)
if result:
promember = 1
-
+
request.session['options'] = options
-
+
return render(request, 'cum_flex.html',
{'interactiveplot':script,
'the_div':div,
@@ -1333,7 +1336,7 @@ def fitnessmetric_view(request,id=0,mode='rower',
startdate=timezone.now()-timezone.timedelta(days=365),
enddate=timezone.now()):
-
+
therower = getrequestrower(request,userid=id)
theuser = therower.user
@@ -1368,7 +1371,7 @@ def fitnessmetric_view(request,id=0,mode='rower',
'name': 'Power Progress'
}
]
-
+
return render(request,'fitnessmetric.html',
{
@@ -1380,7 +1383,7 @@ def fitnessmetric_view(request,id=0,mode='rower',
'mode':mode,
'form':form,
})
-
+
# Show ranking distances including predicted paces
@login_required()
@@ -1420,13 +1423,13 @@ def rankings_view(request,theuser=0,
))
else:
worldclasspower = None
-
+
result = request.user.is_authenticated and ispromember(request.user)
if result:
promember=1
# get all indoor rows in date range
-
+
# process form
if request.method == 'POST' and "daterange" in request.POST:
dateform = DateRangeForm(request.POST)
@@ -1471,7 +1474,7 @@ def rankings_view(request,theuser=0,
allergworkouts = []
r=0
-
+
try:
uu = User.objects.get(id=theuser)
except User.DoesNotExist:
@@ -1491,7 +1494,7 @@ def rankings_view(request,theuser=0,
rankingdurations.sort()
for rankingdistance in rankingdistances:
-
+
workouts = Workout.objects.filter(
user=r,distance=rankingdistance,
workouttype__in=['rower','dynamic','slides'],
@@ -1507,11 +1510,11 @@ def rankings_view(request,theuser=0,
timesecs += 60*workouts[0].duration.minute
timesecs += workouts[0].duration.second
timesecs += 1.e-6*workouts[0].duration.microsecond
-
+
thesecs.append(timesecs)
for rankingduration in rankingdurations:
-
+
workouts = Workout.objects.filter(
user=r,duration=rankingduration,
workouttype='rower',
@@ -1527,7 +1530,7 @@ def rankings_view(request,theuser=0,
timesecs += 60*workouts[0].duration.minute
timesecs += workouts[0].duration.second
timesecs += 1.e-5*workouts[0].duration.microsecond
-
+
thesecs.append(timesecs)
thedistances = np.array(thedistances)
@@ -1599,24 +1602,24 @@ def rankings_view(request,theuser=0,
if pwr2 <= 0:
pwr2 = 50.
-
+
velo2 = (pwr2/2.8)**(1./3.)
if np.isnan(velo2) or velo2 <= 0:
velo2 = 1.0
-
+
t2 = rankingdistance/velo2
-
+
pwr3 = p1[0]/(1+t2/p1[2])
pwr3 += p1[1]/(1+t2/p1[3])
if pwr3 <= 0:
pwr3 = 50.
-
+
velo3 = (pwr3/2.8)**(1./3.)
if np.isnan(velo3) or velo3 <= 0:
velo3 = 1.0
-
+
t3 = rankingdistance/velo3
p3 = 500./velo3
@@ -1664,7 +1667,7 @@ def rankings_view(request,theuser=0,
if np.isnan(velo) or velo <=0:
velo = 1.0
-
+
d = t*velo
p = 500./velo
a = {'distance':int(d),
@@ -1701,7 +1704,7 @@ def ajax_agegrouprecords(request,
sex='female',
weightcategory='hwt',
userid=0):
-
+
wcdurations = []
wcpower = []
durations = [1,4,30,60]
@@ -1717,14 +1720,14 @@ def ajax_agegrouprecords(request,
)
jsondf = df.to_json()
-
+
job = myqueue(queue,
handle_getagegrouprecords,
jsondf,distances,durations,age,sex,weightcategory,
)
-
-
+
+
return JSONResponse(
{
'job':job.id
@@ -1760,13 +1763,13 @@ def rankings_view2(request,theuser=0,
else:
lastupdated = "01-01-1900"
-
+
promember=0
if not request.user.is_anonymous:
r = getrower(request.user)
wcdurations = []
wcpower = []
-
+
lastupdated = "01-01-1900"
userid = 0
if 'options' in request.session:
@@ -1784,7 +1787,7 @@ def rankings_view2(request,theuser=0,
else:
options = {}
-
+
lastupdatedtime = arrow.get(lastupdated).timestamp
current_time = arrow.utcnow().timestamp
@@ -1798,9 +1801,9 @@ def rankings_view2(request,theuser=0,
recalc = False
options['userid'] = theuser
-
+
if r.birthdate:
- age = calculate_age(r.birthdate)
+ age = calculate_age(r.birthdate)
else:
worldclasspower = None
age = 0
@@ -1828,13 +1831,13 @@ def rankings_view2(request,theuser=0,
request.session['options'] = options
-
+
result = request.user.is_authenticated and ispromember(request.user)
if result:
promember=1
# get all indoor rows in date range
-
+
# process form
if request.method == 'POST' and "daterange" in request.POST:
dateform = DateRangeForm(request.POST)
@@ -1879,7 +1882,7 @@ def rankings_view2(request,theuser=0,
allergworkouts = []
r=0
-
+
try:
uu = User.objects.get(id=theuser)
except User.DoesNotExist:
@@ -1902,7 +1905,7 @@ def rankings_view2(request,theuser=0,
rankingdurations.sort()
for rankingdistance in rankingdistances:
-
+
workouts = Workout.objects.filter(
user=r,distance=rankingdistance,
workouttype__in=['rower','dynamic','slides'],
@@ -1917,11 +1920,11 @@ def rankings_view2(request,theuser=0,
timesecs += 60*workouts[0].duration.minute
timesecs += workouts[0].duration.second
timesecs += 1.e-6*workouts[0].duration.microsecond
-
+
thesecs.append(timesecs)
for rankingduration in rankingdurations:
-
+
workouts = Workout.objects.filter(
user=r,duration=rankingduration,
workouttype='rower',
@@ -1936,7 +1939,7 @@ def rankings_view2(request,theuser=0,
timesecs += 60*workouts[0].duration.minute
timesecs += workouts[0].duration.second
timesecs += 1.e-5*workouts[0].duration.microsecond
-
+
thesecs.append(timesecs)
thedistances = np.array(thedistances)
@@ -2014,24 +2017,24 @@ def rankings_view2(request,theuser=0,
if pwr2 <= 0:
pwr2 = 50.
-
+
velo2 = (pwr2/2.8)**(1./3.)
if np.isnan(velo2) or velo2 <= 0:
velo2 = 1.0
-
+
t2 = rankingdistance/velo2
-
+
pwr3 = p1[0]/(1+t2/p1[2])
pwr3 += p1[1]/(1+t2/p1[3])
if pwr3 <= 0:
pwr3 = 50.
-
+
velo3 = (pwr3/2.8)**(1./3.)
if np.isnan(velo3) or velo3 <= 0:
velo3 = 1.0
-
+
t3 = rankingdistance/velo3
p3 = 500./velo3
@@ -2082,7 +2085,7 @@ def rankings_view2(request,theuser=0,
if np.isnan(velo) or velo <=0:
velo = 1.0
-
+
d = t*velo
p = 500./velo
a = {'distance':int(d),
@@ -2107,7 +2110,7 @@ def rankings_view2(request,theuser=0,
)
jsondf = df.to_json()
-
+
job = myqueue(queue,
handle_getagegrouprecords,
jsondf,distances,durations,age,r.sex,r.weightcategory)
@@ -2116,7 +2119,7 @@ def rankings_view2(request,theuser=0,
except KeyError:
request.session['async_tasks'] = [(job.id,'agegrouprecords')]
-
+
messages.error(request,message)
return render(request, 'rankings.html',
@@ -2188,7 +2191,7 @@ def otwrankings_view(request,theuser=0,
promember=1
# get all OTW rows in date range
-
+
# process form
if request.method == 'POST':
dateform = DateRangeForm(request.POST)
@@ -2236,9 +2239,9 @@ def otwrankings_view(request,theuser=0,
request.session['rowerid'] = r.id
except Rower.DoesNotExist:
raise Http404("Rower doesn't exist")
-
-
+
+
try:
uu = User.objects.get(id=theuser)
except User.DoesNotExist:
@@ -2250,12 +2253,12 @@ def otwrankings_view(request,theuser=0,
enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
#enddate = enddate+datetime.timedelta(days=1)
-
+
thedistances = []
theworkouts = []
thesecs = []
-
+
theworkouts = Workout.objects.filter(
user=r,rankingpiece=True,
workouttype='water',
@@ -2269,7 +2272,7 @@ def otwrankings_view(request,theuser=0,
delta,cpvalue,avgpower = dataprep.fetchcp(r,theworkouts)
runningjob = 0
-
+
taskstatus = get_stored_tasks_status(request)
for task in taskstatus:
if task['func_name'] == 'updatecpwater':
@@ -2303,9 +2306,9 @@ def otwrankings_view(request,theuser=0,
try:
request.session['async_tasks'] += [(job.id,'updatecpwater')]
except KeyError:
- request.session['async_tasks'] = [(job.id,'updatecpwater')]
+ request.session['async_tasks'] = [(job.id,'updatecpwater')]
messages.info(request,'New calculation queued. Page will reload automatically. You can check the status of your calculations here')
-
+
powerdf = pd.DataFrame({
'Delta':delta,
'CP':cpvalue,
@@ -2313,7 +2316,7 @@ def otwrankings_view(request,theuser=0,
if powerdf.empty:
messages.info(request,'Your calculations are running in the background. Page will reload automatically. You can check the status of your calculations here')
-
+
powerdf = powerdf[powerdf['CP']>0]
powerdf.dropna(axis=0,inplace=True)
powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True)
@@ -2361,7 +2364,7 @@ def otwrankings_view(request,theuser=0,
pwr = p1[0]/(1+t/p1[2])
pwr += p1[1]/(1+t/p1[3])
-
+
if pwr <= 0:
pwr = 50.
@@ -2457,7 +2460,7 @@ def otecp_toadmin_view(request,theuser=0,
csvfilename = 'CP_data_user_{id}.csv'.format(
id = theuser
)
-
+
powerdf = powerdf[powerdf['CP']>0]
powerdf.dropna(axis=0,inplace=True)
powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True)
@@ -2527,7 +2530,7 @@ def otwcp_toadmin_view(request,theuser=0,
csvfilename = 'CP_data_user_{id}.csv'.format(
id = theuser
)
-
+
powerdf = powerdf[powerdf['CP']>0]
powerdf.dropna(axis=0,inplace=True)
powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True)
@@ -2594,7 +2597,7 @@ def oterankings_view(request,theuser=0,
promember=1
# get all OTW rows in date range
-
+
# process form
if request.method == 'POST':
dateform = DateRangeForm(request.POST)
@@ -2619,14 +2622,14 @@ def oterankings_view(request,theuser=0,
trankingdistances = form.cleaned_data['trankingdistances']
except KeyError:
trankingdistances = []
-
+
trankingdistances = [int(d) for d in trankingdistances]
try:
trankingdurations = form.cleaned_data['trankingdurations']
except KeyError:
trankingdurations = []
-
+
trankingdurations = [
datetime.datetime.strptime(d,"%H:%M:%S").time() for d in trankingdurations
]
@@ -2664,7 +2667,7 @@ def oterankings_view(request,theuser=0,
allergworkouts = []
raise Http404("Rower doesn't exist")
-
+
try:
uu = User.objects.get(id=theuser)
except User.DoesNotExist:
@@ -2675,12 +2678,12 @@ def oterankings_view(request,theuser=0,
startdate = datetime.datetime.combine(startdate,datetime.time())
enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
-
-
+
+
thedistances = []
theworkouts = []
thesecs = []
-
+
theworkouts = Workout.objects.filter(
user=r,rankingpiece=True,
workouttype__in=workouttypes,
@@ -2694,7 +2697,7 @@ def oterankings_view(request,theuser=0,
)
runningjob = 0
-
+
taskstatus = get_stored_tasks_status(request)
for task in taskstatus:
if task['func_name'] == 'updatecp':
@@ -2716,7 +2719,7 @@ def oterankings_view(request,theuser=0,
messages.info(request,'Getting ready to update CP chart data')
runningjob = 1
-
+
if not runningjob:
job = dataprep.runcpupdate(
r,type='rower',
@@ -2737,7 +2740,7 @@ def oterankings_view(request,theuser=0,
if powerdf.empty:
messages.info(request,'Your calculations are running in the background. Page will reload automatically. You can check the status of your calculations here')
-
+
powerdf = powerdf[powerdf['CP']>0]
powerdf.dropna(axis=0,inplace=True)
powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True)
@@ -2791,7 +2794,7 @@ def oterankings_view(request,theuser=0,
velo = (pwr/2.8)**(1./3.)
p = 500./velo
d = t*velo
-
+
if pwr <= 0:
pwr = 50.
@@ -2822,17 +2825,17 @@ def oterankings_view(request,theuser=0,
pace_10 = 500./velo_10
distance_10 = t_10*velo_10
- paulslope = 5.
-
+ paulslope = 5.
+
for rankingdistance in trankingdistances:
delta = paulslope * np.log(rankingdistance/distance_10)/np.log(2)
-
-
+
+
p = pace_10+delta
velo = 500./p
t = rankingdistance/velo
-
+
pwr2 = p1[0]/(1+t/p1[2])
pwr2 += p1[1]/(1+t/p1[3])
try:
@@ -2842,26 +2845,26 @@ def oterankings_view(request,theuser=0,
if pwr2 <= 0:
pwr2 = 50.
-
+
velo2 = (pwr2/2.8)**(1./3.)
if np.isnan(velo2) or velo2 <= 0:
velo2 = 1.0
-
+
t2 = rankingdistance/velo2
-
+
pwr3 = p1[0]/(1+t2/p1[2])
pwr3 += p1[1]/(1+t2/p1[3])
pwr3 *= ratio
-
+
if pwr3 <= 0:
pwr3 = 50.
-
+
velo3 = (pwr3/2.8)**(1./3.)
if np.isnan(velo3) or velo3 <= 0:
velo3 = 1.0
-
+
t3 = rankingdistance/velo3
p3 = 500./velo3
@@ -2898,7 +2901,7 @@ def oterankings_view(request,theuser=0,
})
-
+
# Multi Flex Chart with Grouping
@user_passes_test(ispromember,login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher",
@@ -2914,7 +2917,7 @@ def user_multiflex_select(request,
r = getrequestrower(request,userid=userid)
user = r.user
-
+
if 'options' in request.session:
options = request.session['options']
else:
@@ -2924,7 +2927,7 @@ def user_multiflex_select(request,
palette = request.session['palette']
except KeyError:
palette = 'monochrome_blue'
-
+
try:
includereststrokes = request.session['includereststrokes']
except KeyError:
@@ -2934,7 +2937,7 @@ def user_multiflex_select(request,
ploterrorbars = request.session['ploterrorbars']
except:
ploterrorbars = False
-
+
if 'startdate' in request.session:
startdate = iso8601.parse_date(request.session['startdate'])
@@ -2953,8 +2956,8 @@ def user_multiflex_select(request,
rankingonly = request.session['rankingonly']
else:
rankingonly = False
-
-
+
+
if 'modalities' in request.session:
modalities = request.session['modalities']
if len(modalities) > 1:
@@ -2964,7 +2967,7 @@ def user_multiflex_select(request,
else:
modalities = [m[0] for m in mytypes.workouttypes]
modality = 'all'
-
+
if request.method == 'POST':
dateform = DateRangeForm(request.POST)
if dateform.is_valid():
@@ -2987,7 +2990,7 @@ def user_multiflex_select(request,
if modality != 'water':
waterboattype = [b[0] for b in mytypes.boattypes]
-
+
request.session['modalities'] = modalities
request.session['waterboattype'] = waterboattype
request.session['rankingonly'] = rankingonly
@@ -2997,7 +3000,7 @@ def user_multiflex_select(request,
'enddate':enddate,
})
-
+
startdate = datetime.datetime.combine(startdate,datetime.time())
enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
#enddate = enddate+datetime.timedelta(days=1)
@@ -3022,7 +3025,7 @@ def user_multiflex_select(request,
rankingpiece = [True]
else:
rankingpiece = [True,False]
-
+
workouts = Workout.objects.filter(
user=r,
startdatetime__gte=startdate,
@@ -3074,7 +3077,7 @@ def user_multiflex_select(request,
request.session['waterboattype'] = waterboattype
request.session['rankingonly'] = rankingonly
request.session['modalities'] = modalities
-
+
breadcrumbs = [
{
@@ -3128,7 +3131,7 @@ def multiflex_data(request,userid=0,
}):
def_options = options
-
+
if 'options' in request.session:
options = request.session['options']
@@ -3146,13 +3149,13 @@ def multiflex_data(request,userid=0,
palette = request.session['palette']
except KeyError:
palette = 'monochrome_blue'
-
+
workstrokesonly = not includereststrokes
if userid==0:
userid = request.user.id
-
+
palette = keyvalue_get_default('palette',options, def_options)
groupby = keyvalue_get_default('groupby',options, def_options)
binsize = keyvalue_get_default('binsize',options, def_options)
@@ -3165,7 +3168,7 @@ def multiflex_data(request,userid=0,
ids = keyvalue_get_default('ids',options, def_options)
workouts = []
-
+
for id in ids:
try:
workouts.append(Workout.objects.get(id=id))
@@ -3175,12 +3178,12 @@ def multiflex_data(request,userid=0,
labeldict = {
int(w.id): w.__str__() for w in workouts
}
-
+
fieldlist,fielddict = dataprep.getstatsfields()
fieldlist = [xparam,yparam,groupby,
'workoutid','spm','driveenergy',
'workoutstate']
-
+
# prepare data frame
datadf,extracols = dataprep.read_cols_df_sql(ids,fieldlist)
@@ -3238,9 +3241,9 @@ def multiflex_data(request,userid=0,
)
groups = datadf.groupby(pd.cut(datadf['days ago'], bins,
labels=False))
-
- xvalues = groups.mean()[xparam]
+
+ xvalues = groups.mean()[xparam]
yvalues = groups.mean()[yparam]
xerror = groups.std()[xparam]
yerror = groups.std()[yparam]
@@ -3266,7 +3269,7 @@ def multiflex_data(request,userid=0,
return HttpResponseRedirect(url)
else:
groupsize = 30.*np.sqrt(groupsize/float(groupsize.max()))
-
+
df = pd.DataFrame({
xparam:xvalues,
yparam:yvalues,
@@ -3280,14 +3283,14 @@ def multiflex_data(request,userid=0,
if yparam == 'pace':
df['y'] = dataprep.paceformatsecs(df['y']/1.0e3)
-
+
aantal = len(df)
-
+
if groupby != 'date':
try:
df['groupval'] = groups.mean()[groupby]
df['groupval'].loc[mask] = np.nan
-
+
groupcols = df['groupval']
except ValueError:
df['groupval'] = groups.mean()[groupby].fillna(value=0)
@@ -3296,7 +3299,7 @@ def multiflex_data(request,userid=0,
except KeyError:
messages.error(request,'Data selection error')
url = reverse(user_multiflex_select)
- return HttpResponseRedirect(url)
+ return HttpResponseRedirect(url)
else:
try:
dates = groups.min()[groupby]
@@ -3308,16 +3311,16 @@ def multiflex_data(request,userid=0,
except AttributeError:
df['groupval'] = groups.mean()['days ago'].fillna(value=0)
groupcols = 100.*np.arange(aantal)/float(aantal)
-
-
+
+
groupcols = (groupcols-groupcols.min())/(groupcols.max()-groupcols.min())
if aantal == 1:
groupcols = np.array([1.])
-
+
colors = range_to_color_hex(groupcols,palette=palette)
-
+
df['color'] = colors
clegendx = np.arange(0,1.2,.2)
@@ -3328,7 +3331,7 @@ def multiflex_data(request,userid=0,
clegendy = df.index.min()+clegendx*(df.index.max()-df.index.min())
-
+
colorlegend = zip(range(6),clegendy,legcolors)
@@ -3337,9 +3340,9 @@ def multiflex_data(request,userid=0,
else:
u = User.objects.get(id=userid)
extratitle = ' '+u.first_name+' '+u.last_name
-
-
+
+
script,div = interactive_multiflex(df,xparam,yparam,
groupby,
extratitle=extratitle,
@@ -3348,16 +3351,16 @@ def multiflex_data(request,userid=0,
colorlegend=colorlegend,
spmmin=spmmin,spmmax=spmmax,
workmin=workmin,workmax=workmax)
-
+
scripta= script.split('\n')[2:-1]
script = ''.join(scripta)
-
+
return JSONResponse({
"script":script,
"div":div,
- })
-
+ })
+
@user_passes_test(ispromember,login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher",
@@ -3385,7 +3388,7 @@ def multiflex_view(request,userid=0,
palette = request.session['palette']
except KeyError:
palette = 'monochrome_blue'
-
+
if 'startdate' in request.session:
startdate = iso8601.parse_date(request.session['startdate'])
@@ -3397,7 +3400,7 @@ def multiflex_view(request,userid=0,
if userid==0:
userid = request.user.id
-
+
if request.method == 'POST' and 'workouts' in request.POST:
form = WorkoutMultipleCompareForm(request.POST)
chartform = MultiFlexChoiceForm(request.POST)
@@ -3411,14 +3414,14 @@ def multiflex_view(request,userid=0,
workstrokesonly = not includereststrokes
palette = chartform.cleaned_data['palette']
-
+
groupby = chartform.cleaned_data['groupby']
binsize = chartform.cleaned_data['binsize']
if binsize <= 0:
binsize = 1
if groupby == 'pace':
binsize *= 1000
-
+
spmmin = chartform.cleaned_data['spmmin']
spmmax = chartform.cleaned_data['spmmax']
workmin = chartform.cleaned_data['workmin']
@@ -3447,7 +3450,7 @@ def multiflex_view(request,userid=0,
binsize = 1
if groupby == 'pace':
binsize *= 1000.
-
+
spmmin = chartform.cleaned_data['spmmin']
spmmax = chartform.cleaned_data['spmmax']
workmin = chartform.cleaned_data['workmin']
@@ -3465,7 +3468,7 @@ def multiflex_view(request,userid=0,
}
)
return HttpResponseRedirect(url)
-
+
# workouts = [Workout.objects.get(id=id) for id in ids]
@@ -3495,7 +3498,7 @@ def multiflex_view(request,userid=0,
request.session['options'] = options
r = getrequestrower(request,userid=userid)
-
+
breadcrumbs = [
{
'url':'/rowers/analysis',
@@ -3510,7 +3513,7 @@ def multiflex_view(request,userid=0,
'name': 'Trend Flex Chart'
}
]
-
+
return render(request,'multiflex.html',
{'interactiveplot':'',
@@ -3547,10 +3550,10 @@ def user_boxplot_select(request,
r = getrequestrower(request,userid=userid)
user = r.user
userid = user.id
-
+
if 'options' in request.session:
options = request.session['options']
-
+
try:
workouttypes = options['workouttypes']
@@ -3561,7 +3564,7 @@ def user_boxplot_select(request,
rankingonly = options['rankingonly']
except KeyError:
rankingonly = False
-
+
try:
includereststrokes = options['includereststrokes']
except KeyError:
@@ -3616,7 +3619,7 @@ def user_boxplot_select(request,
rankingonly = optionsform.cleaned_data['rankingonly']
else:
rankingonly = False
-
+
request.session['modalities'] = modalities
request.session['waterboattype'] = waterboattype
else:
@@ -3675,7 +3678,7 @@ def user_boxplot_select(request,
if rankingonly:
workouts = workouts.exclude(rankingpiece=False)
-
+
query = request.GET.get('q')
if query:
query_list = query.split()
@@ -3698,7 +3701,7 @@ def user_boxplot_select(request,
'waterboattype':waterboattype,
'rankingonly':rankingonly,
})
-
+
messages.info(request,successmessage)
messages.error(request,message)
@@ -3771,7 +3774,7 @@ def boxplot_view_data(request,userid=0,
userid = 0
plotfield = 'spm'
-
+
workstrokesonly = not includereststrokes
if userid==0:
@@ -3791,27 +3794,27 @@ def boxplot_view_data(request,userid=0,
workouts.append(Workout.objects.get(id=id))
except Workout.DoesNotExist:
pass
-
+
labeldict = {
int(w.id): w.__str__() for w in workouts
}
-
-
+
+
datemapping = {
w.id:w.date for w in workouts
}
-
-
+
+
fieldlist,fielddict = dataprep.getstatsfields()
fieldlist = [plotfield,'workoutid','spm','driveenergy',
'workoutstate']
-
+
# prepare data frame
datadf,extracols = dataprep.read_cols_df_sql(ids,fieldlist)
-
+
datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly)
datadf = dataprep.filter_df(datadf,'spm',spmmin,
@@ -3835,22 +3838,22 @@ def boxplot_view_data(request,userid=0,
else:
u = User.objects.get(id=userid)
extratitle = ' '+u.first_name+' '+u.last_name
-
-
+
+
script,div = interactive_boxchart(datadf,plotfield,
extratitle=extratitle,
spmmin=spmmin,spmmax=spmmax,workmin=workmin,workmax=workmax)
scripta = script.split('\n')[2:-1]
script = ''.join(scripta)
-
+
return JSONResponse({
"script":script,
"div":div,
})
-
+
@user_passes_test(ispromember,login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher",
redirect_field_name=None)
@@ -3876,13 +3879,13 @@ def boxplot_view(request,userid=0,
except KeyError:
rankingonly = False
options['rankingonly'] = False
-
+
workstrokesonly = not includereststrokes
if userid==0:
userid = request.user.id
-
+
if request.method == 'POST' and 'workouts' in request.POST:
form = WorkoutMultipleCompareForm(request.POST)
chartform = BoxPlotChoiceForm(request.POST)
@@ -3969,7 +3972,7 @@ def boxplot_view(request,userid=0,
'teams':get_my_teams(request.user),
})
-
+
# Cumulative stats page
@user_passes_test(ispromember,login_url="/rowers/paidplans",message="This functionality requires a Pro plan or higher",redirect_field_name=None)
def cumstats(request,theuser=0,
@@ -3987,13 +3990,13 @@ def cumstats(request,theuser=0,
r = getrequestrower(request,userid=theuser)
theuser = r.user
-
+
if 'waterboattype' in request.session:
waterboattype = request.session['waterboattype']
else:
waterboattype = mytypes.waterboattype
-
+
if 'rankingonly' in request.session:
rankingonly = request.session['rankingonly']
else:
@@ -4014,7 +4017,7 @@ def cumstats(request,theuser=0,
rankingonly = options['rankingonly']
except KeyError:
rankingonly = False
-
+
try:
includereststrokes = options['includereststrokes']
except KeyError:
@@ -4037,9 +4040,9 @@ def cumstats(request,theuser=0,
enddate = startdate
startdate = s
-
+
# get all indoor rows of in date range
-
+
# process form
if request.method == 'POST':
form = DateRangeForm(request.POST)
@@ -4065,7 +4068,7 @@ def cumstats(request,theuser=0,
if modality != 'water':
waterboattype = [b[0] for b in mytypes.boattypes]
-
+
request.session['modalities'] = modalities
request.session['waterboattype'] = waterboattype
request.session['rankingonly'] = rankingonly
@@ -4100,7 +4103,7 @@ def cumstats(request,theuser=0,
div = get_call()
js_resources = ''
css_resources = ''
-
+
options = {
'modality': modality,
'theuser': theuser.id,
@@ -4111,7 +4114,7 @@ def cumstats(request,theuser=0,
'includereststrokes':includereststrokes,
}
-
+
request.session['options'] = options
@@ -4119,7 +4122,7 @@ def cumstats(request,theuser=0,
modalities = [m[0] for m in mytypes.workouttypes]
else:
modalities = [modality]
-
+
try:
startdate = iso8601.parse_date(startdatestring)
except ParseError:
@@ -4152,7 +4155,7 @@ def cumstats(request,theuser=0,
rankingpiece = [True,]
else:
rankingpiece = [True,False]
-
+
allworkouts = Workout.objects.filter(
user=r2,
workouttype__in=modalities,
@@ -4168,21 +4171,21 @@ def cumstats(request,theuser=0,
w.id:w.date for w in allworkouts
}
-
-
+
+
fieldlist,fielddict = dataprep.getstatsfields()
-
+
# prepare data frame
datadf,extracols = dataprep.read_cols_df_sql(ids,fieldlist)
datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly)
request.session['rowerid'] = r.id
-
+
if datadf.empty:
stats = {}
cordict = {}
-
+
response = render(request,
'cumstats.html',
{
@@ -4201,7 +4204,7 @@ def cumstats(request,theuser=0,
})
request.session['options'] = options
-
+
return response
@@ -4246,7 +4249,7 @@ def cumstats(request,theuser=0,
initial['waterboattype'] = waterboattype
initial['rankingonly'] = rankingonly
-
+
response = render(request,
'cumstats.html',
{
@@ -4305,12 +4308,12 @@ def agegrouprecordview(request,sex='male',weightcategory='hwt',
).values()
)
)
-
+
script,div = interactive_agegroup_plot(df,sex=sex,distance=distance,
duration=duration,
weightcategory=weightcategory)
-
+
return render(request, 'agegroupchart.html',
{
'interactiveplot':script,
@@ -4328,11 +4331,11 @@ def alerts_view(request,userid=0):
alerts = Alert.objects.filter(rower=r).order_by('next_run')
stats = []
-
+
for alert in alerts:
stats.append(alert_get_stats(alert))
-
+
breadcrumbs = [
{
'url':'/rowers/analysis',
@@ -4401,13 +4404,13 @@ def alert_create_view(request,userid=0):
if result:
messages.info(request,message)
-
+
url = reverse('alert_edit_view',kwargs={'id':result})
return HttpResponseRedirect(url)
else:
form = AlertEditForm()
measuredform = ConditionEditForm()
-
+
breadcrumbs = [
{
'url':'/rowers/analysis',
@@ -4449,7 +4452,7 @@ def alert_report_view(request,id=0,userid=0,nperiod=0):
except Alert.DoesNotExist:
raise Http404("This alert doesn't exist")
-
+
if alert.manager != request.user:
raise PermissionDenied('You are not allowed to edit this Alert')
@@ -4488,7 +4491,7 @@ def alert_report_view(request,id=0,userid=0,nperiod=0):
'alert':alert,
'nperiod':nperiod,
})
-
+
# alert edit view
@user_passes_test(ispromember, login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher",
@@ -4501,7 +4504,7 @@ def alert_edit_view(request,id=0,userid=0):
except Alert.DoesNotExist:
raise Http404("This alert doesn't exist")
-
+
if alert.manager != request.user:
raise PermissionDenied('You are not allowed to edit this Alert')
@@ -4514,7 +4517,7 @@ def alert_edit_view(request,id=0,userid=0):
'value2':m.value2,
'condition':m.condition}
for m in alert.filter.all()]
-
+
if request.method == 'POST':
form = AlertEditForm(request.POST)
measuredform = ConditionEditForm(request.POST)
@@ -4544,7 +4547,7 @@ def alert_edit_view(request,id=0,userid=0):
alert.boattype = boattype
alert.name = name
alert.save()
-
+
filters = []
for filter_form in filter_formset:
@@ -4588,7 +4591,7 @@ def alert_edit_view(request,id=0,userid=0):
},
]
-
+
return render(request,'alert_edit.html',
{
'breadcrumbs':breadcrumbs,
diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py
index 1c108ad9..e152acf1 100644
--- a/rowers/views/workoutviews.py
+++ b/rowers/views/workoutviews.py
@@ -2796,18 +2796,21 @@ def workout_stats_view(request,id=0,message="",successmessage=""):
pass
for field,verbosename in fielddict.items():
- thedict = {
- 'mean':datadf[field].mean(),
- 'wmean': wavg(datadf, field, 'deltat'),
- 'min': datadf[field].min(),
- 'std': datadf[field].std(),
- 'max': datadf[field].max(),
- 'median': datadf[field].median(),
- 'firstq':datadf[field].quantile(q=0.25),
- 'thirdq':datadf[field].quantile(q=0.75),
- 'verbosename':verbosename,
- }
- stats[field] = thedict
+ try:
+ thedict = {
+ 'mean':datadf[field].mean(),
+ 'wmean': wavg(datadf, field, 'deltat'),
+ 'min': datadf[field].min(),
+ 'std': datadf[field].std(),
+ 'max': datadf[field].max(),
+ 'median': datadf[field].median(),
+ 'firstq':datadf[field].quantile(q=0.25),
+ 'thirdq':datadf[field].quantile(q=0.75),
+ 'verbosename':verbosename,
+ }
+ stats[field] = thedict
+ except KeyError:
+ pass
# Create a dict with correlation values
cor = datadf.corr(method='spearman')