Private
Public Access
1
0

a few more tests and removing old code

This commit is contained in:
Sander Roosendaal
2021-01-11 20:43:37 +01:00
parent e153e63481
commit 394d80d040
6 changed files with 47 additions and 487 deletions

View File

@@ -312,12 +312,6 @@ def mapcolors(x):
except KeyError:
return mytypes.colors[-1]
def maptypes(x):
try:
return mytypes.workouttypes_ordered[x]
except KeyError:
return 'Other'
def interactive_workouttype_piechart(workouts):
if len(workouts) == 0:
return "","Not enough workouts to make a chart"
@@ -2092,171 +2086,6 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
def fitnessmetric_chart(fitnessmetrics,user,workoutmode='rower',startdate=None,
enddate=None):
power4min = [int(m.PowerFourMin) for m in fitnessmetrics]
power2k = [int(m.PowerTwoK) for m in fitnessmetrics]
power1hr = [int(m.PowerOneHour) for m in fitnessmetrics]
dates = [m.date for m in fitnessmetrics]
mode = [m.workoutmode for m in fitnessmetrics]
if len(power4min) == 0:
return ['','']
df = pd.DataFrame(
{'power4min':power4min,
'power2k':power2k,
'power1hr':power1hr,
'date':dates,
'dates':dates,
'mode':mode
})
delta = df['power4min'].astype('int').diff()
mask = delta == 0
df.loc[mask,'power4min'] = np.nan
df.dropna(inplace=True,axis=0,how='any')
df = df[df['power2k']>0]
try:
df = df[df['mode']==workoutmode]
except TypeError:
df = pd.DataFrame()
if df.empty:
return ["","no data"]
groups = df.groupby(by='date').max()
power4min = groups['power4min']
date = groups['dates']
power2k = groups['power2k']
power1hr = groups['power1hr']
source = ColumnDataSource(
data = dict(
power4min = power4min,
power2k = power2k,
date = date,
power1hr = power1hr,
fdate=groups['dates'].map(lambda x: x.strftime('%Y-%m-%d'))
)
)
# fit
resampled = groups.set_index('dates')
resampled.index = pd.to_datetime(resampled.index)
resampled = resampled.resample('D').interpolate(
method='linear',order=2)
power4min = resampled['power4min']
date = resampled.index.values
power2k = resampled['power2k']
power1hr = resampled['power1hr']
source2 = ColumnDataSource(
data = dict(
power4min = power4min,
power2k = power2k,
date = date,
power1hr = power1hr,
fdate=resampled.index.map(lambda x: x.strftime('%d-%m-%Y')) )
)
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
plot = Figure(tools=TOOLS,toolbar_location="above",
toolbar_sticky=False,width=900,
x_axis_type='datetime')
# add watermark
watermarkurl = "/static/img/logo7.png"
watermarksource = ColumnDataSource(dict(
url = [watermarkurl],))
watermarkrange = Range1d(start=0,end=1)
watermarkalpha = 0.6
watermarkx = 0.99
watermarky = 0.01
watermarkw = 184
watermarkh = 35
watermarkanchor = 'bottom_right'
plot.extra_y_ranges = {"watermark": watermarkrange}
plot.extra_x_ranges = {"watermark": watermarkrange}
plot.image_url([watermarkurl],watermarkx,watermarky,
watermarkw,watermarkh,
global_alpha=watermarkalpha,
w_units='screen',
h_units='screen',
anchor=watermarkanchor,
dilate=True,
x_range_name = "watermark",
y_range_name = "watermark",
)
plot.circle('date','power2k',source=source,fill_color='red',size=10,
legend_label='2k power')
plot.circle('date','power1hr',source=source,fill_color='blue',size=10,
legend_label='1 hr power')
plot.circle('date','power4min',source=source,fill_color='green',size=10,
legend_label='4 min power')
plot.line('date','power4min',source=source2,color='green')
plot.line('date','power2k',source=source2,color='red')
plot.line('date','power1hr',source=source2,color='blue')
plot.xaxis.axis_label = 'Date'
plot.yaxis.axis_label = 'Power (W)'
plot.xaxis.formatter = DatetimeTickFormatter(
days=["%d %B %Y"],
months=["%d %B %Y"],
years=["%d %B %Y"],
)
plot.xaxis.major_label_orientation = pi/4
plot.sizing_mode = 'stretch_both'
plot.y_range = Range1d(0,1.5*max(power4min))
startdate = datetime.datetime.combine(startdate,datetime.datetime.min.time())
enddate = datetime.datetime.combine(enddate,datetime.datetime.min.time())
if not startdate:
startdate = datetime.datetime.combine(min(date), datetime.datetime.min.time())
if not enddate:
enddate = datetime.datetime.combine(max(date), datetime.datetime.min.time())
plot.x_range = Range1d(
startdate,enddate,
)
plot.title.text = 'Power levels ('+workoutmode+') from workouts '+user.first_name
hover = plot.select(dict(type=HoverTool))
hover.tooltips = OrderedDict([
('Power 4 minutes','@power4min'),
('Power 2000 m','@power2k'),
('Power 1 hour','@power1hr'),
('Date','@fdate'),
])
script,div = components(plot)
return [script,div]
def interactive_histoall(theworkouts,histoparam,includereststrokes,
spmmin=0,spmmax=55,
@@ -6678,255 +6507,6 @@ def interactive_multiple_compare_chart(ids,xparam,yparam,plottype='line',
def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm',
promember=0,plottype='line'):
columns = [xparam,yparam,
'ftime','distance','fpace',
'power','hr','spm',
'time','pace','workoutstate']
# check if valid ID exists (workout exists)
#rowdata1,row1 = dataprep.getrowdata_db(id=id1)
#rowdata2,row2 = dataprep.getrowdata_db(id=id2)
rowdata1 = dataprep.getsmallrowdata_db(columns,ids=[id1])
rowdata2 = dataprep.getsmallrowdata_db(columns,ids=[id2])
for n in ['distance','power','hr','spm','time','pace','workoutstate']:
try:
rowdata1[n].fillna(value=0,inplace=True)
except KeyError:
pass
try:
rowdata2[n].fillna(value=0,inplace=True)
except KeyError:
pass
rowdata1.dropna(axis=1,how='all',inplace=True)
rowdata1.dropna(axis=0,how='any',inplace=True)
rowdata2.dropna(axis=1,how='all',inplace=True)
rowdata2.dropna(axis=0,how='any',inplace=True)
row1 = Workout.objects.get(id=id1)
row2 = Workout.objects.get(id=id2)
if rowdata1.empty:
return "","No Valid Data Available"
# else:
# rowdata1.sort_values(by='time',ascending=True,inplace=True)
if rowdata2.empty:
return "","No Valid Data Available"
# else:
# rowdata2.sort_values(by='time',ascending=True,inplace=True)
try:
x1 = rowdata1.loc[:,xparam]
x2 = rowdata2.loc[:,xparam]
y1 = rowdata1.loc[:,yparam]
y2 = rowdata2.loc[:,yparam]
except KeyError:
return "","No valid Data Available"
x_axis_type = 'linear'
y_axis_type = 'linear'
if xparam == 'time':
x_axis_type = 'datetime'
if yparam == 'pace':
y_axis_type = 'datetime'
ymax = 1.0e3*90
ymin = 1.0e3*180
if row1.workouttype == 'water':
ymax = 1.0e3*90
ymin = 1.0e3*210
ftime1 = rowdata1.loc[:,'ftime']
ftime2 = rowdata2.loc[:,'ftime']
hr1 = rowdata1.loc[:,'hr']
hr2 = rowdata2.loc[:,'hr']
fpace1 = rowdata1.loc[:,'fpace']
fpace2 = rowdata2.loc[:,'fpace']
distance1 = rowdata1.loc[:,'distance']
distance2 = rowdata2.loc[:,'distance']
spm1 = rowdata1.loc[:,'spm']
spm2 = rowdata2.loc[:,'spm']
if (promember==1):
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
else:
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
data1 = pd.DataFrame(
dict(
x1=x1,
y1=y1,
ftime1=ftime1,
fpace1=fpace1,
hr1 = hr1,
spm1 = spm1,
distance1=distance1,
)
).dropna()
data2 = pd.DataFrame(
dict(
x2=x2,
y2=y2,
ftime2=ftime2,
fpace2=fpace2,
hr2 = hr2,
spm2 = spm2,
distance2=distance2,
)
).dropna()
source1 = ColumnDataSource(
data1
)
source2 = ColumnDataSource(
data2
)
ymean1 = data1['y1'].mean()
ymean2 = data2['y2'].mean()
# create interactive plot
plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
tools=TOOLS,
plot_width=920,
toolbar_sticky=False)
# add watermark
watermarkurl = "/static/img/logo7.png"
watermarksource = ColumnDataSource(dict(
url = [watermarkurl],))
watermarkrange = Range1d(start=0,end=1)
watermarkalpha = 0.6
watermarkx = 0.99
watermarky = 0.01
watermarkw = 184
watermarkh = 35
watermarkanchor = 'bottom_right'
plot.extra_y_ranges = {"watermark": watermarkrange}
plot.extra_x_ranges = {"watermark": watermarkrange}
plot.sizing_mode = 'stretch_both'
plot.image_url([watermarkurl],0.05,watermarky,
watermarkw,watermarkh,
global_alpha=watermarkalpha,
w_units='screen',
h_units='screen',
anchor='bottom_left',
dilate=True,
x_range_name = "watermark",
y_range_name = "watermark",
)
TIPS = OrderedDict([
('time','@ftime1'),
('pace','@fpace1'),
('hr','@hr1'),
('spm','@spm1{1.1}'),
('distance','@distance1{5}'),
])
TIPS2 = OrderedDict([
('time','@ftime2'),
('pace','@fpace2'),
('hr','@hr2'),
('spm','@spm2{1.1}'),
('distance','@distance2{5}'),
])
hover1 = plot.select(type=HoverTool)
hover1.tooltips = TIPS
hover2 = plot.select(type=HoverTool)
hover2.tooltips = TIPS2
if plottype=='line':
l1 = plot.line('x1','y1',source=source1,
color="blue",legend_label=row1.name,
)
l2 = plot.line('x2','y2',source=source2,
color="red",legend_label=row2.name,
)
elif plottype=='scatter':
l1 = plot.scatter('x1','y1',source=source1,legend_label=row1.name,
fill_alpha=0.4,
line_color=None)
l2 = plot.scatter('x2','y2',source=source2,legend_label=row2.name,
fill_alpha=0.4,
line_color=None,color="red")
plot.add_tools(HoverTool(renderers=[l1],tooltips=TIPS))
plot.add_tools(HoverTool(renderers=[l2],tooltips=TIPS2))
plot.legend.location = "bottom_right"
plot.title.text = row1.name+' vs '+row2.name
plot.title.text_font_size=value("1.2em")
plot.xaxis.axis_label = axlabels[xparam]
plot.yaxis.axis_label = axlabels[yparam]
ylabel1 = Label(x=100,y=90,x_units='screen',y_units='screen',
text=axlabels[yparam]+": {ymean1:6.2f}".format(
ymean1=ymean1
),
background_fill_alpha=.7,
background_fill_color='white',
text_color='blue'
)
ylabel2 = Label(x=100,y=110,x_units='screen',y_units='screen',
text=axlabels[yparam]+": {ymean2:6.2f}".format(
ymean2=ymean2
),
background_fill_alpha=.7,
background_fill_color='white',
text_color='red'
)
plot.add_layout(ylabel1)
plot.add_layout(ylabel2)
if xparam == 'time':
plot.xaxis[0].formatter = DatetimeTickFormatter(
hours = ["%H"],
minutes = ["%M"],
seconds = ["%S"],
days = ["0"],
months = [""],
years = [""]
)
if yparam == 'pace':
plot.yaxis[0].formatter = DatetimeTickFormatter(
seconds = ["%S"],
minutes = ["%M"]
)
plot.y_range = Range1d(ymin,ymax)
script, div = components(plot)
return [script,div]
def interactive_otw_advanced_pace_chart(id=0,promember=0):
# check if valid ID exists (workout exists)

View File

@@ -1000,9 +1000,28 @@ class GoldMedalScores(TestCase):
self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(20, user=self.r)
ws = Workout.objects.all().order_by('date')
ws[0].rankingpiece = True
ws[0].save()
result = get_random_file(filename='rowers/tests/testdata/onwater2.csv')
self.w1 = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=result['starttime'],
startdatetime=result['startdatetime'],
duration=result['duration'],
distance=result['totaldist'],
workouttype = 'water',
rankingpiece=True
)
result = get_random_file(filename='rowers/tests/testdata/onwater2.csv')
self.w2 = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=result['starttime'],
startdatetime=result['startdatetime'],
duration=result['duration'],
distance=result['totaldist'],
workouttype = 'water',
rankingpiece=True
)
self.factory = RequestFactory()
self.password = faker.word()
self.u.set_password(self.password)
@@ -1020,6 +1039,9 @@ class GoldMedalScores(TestCase):
def test_workouts_goldmedalscores(self, mocked_sqlalchemy,
mocked_getsmallrowdata_db):
ws = Workout.objects.filter(rankingpiece=True)
self.assertEqual(ws.count(),2)
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)

View File

@@ -71,7 +71,10 @@ class InteractivePlotTests(TestCase):
self.assertFalse(len(script)==0)
self.assertFalse(len(div)==0)
def test_interactive_chart(self):
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
def test_interactive_chart(self, mocked_sqlalchemy,
mocked_getsmallrowdata_db):
workout = Workout.objects.filter(user=self.r,workouttype__in=mytypes.rowtypes)[0]
id = workout.id
@@ -99,3 +102,14 @@ class InteractivePlotTests(TestCase):
script, div = interactiveplots.interactive_chart_video(data)
self.assertFalse(len(script)==0)
self.assertFalse(len(div)==0)
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
def test_interactive_flexchart_stacked(self, mocked_sqlalchemy,
mocked_getsmallrowdata_db):
workout = Workout.objects.filter(user=self.r,workouttype__in=mytypes.rowtypes)[0]
id = workout.id
script, div, js_res, css_res, comment = interactiveplots.interactive_flexchart_stacked(id,self.r)
self.assertFalse(len(script)==0)
self.assertFalse(len(div)==0)

View File

@@ -205,9 +205,10 @@ class TestForceUnit(TestCase):
average_N = int(row.df[' AverageDriveForce (N)'].mean())
self.assertEqual(average_N,398)
df = dataprep.getsmallrowdata_db(['averageforce'],ids=[w[0].id],doclean=False,
compute=False)
rowdata = dataprep.rdata('rowers/tests/testdata/PainsledForce.csv')
df = dataprep.dataprep(rowdata.df)
#df = dataprep.getsmallrowdata_db(['averageforce'],ids=[w[0].id],doclean=False,
# compute=False)
try:
average_N = int(df['averageforce'].mean())
if average_N != 0:

View File

@@ -349,9 +349,9 @@ urlpatterns = [
re_path(r'^record-progress/$',views.post_progress),
re_path(r'^list-graphs/$',views.graphs_view,name='graphs_view'),
re_path(r'^list-graphs/user/(?P<userid>\d+)/$',views.graphs_view,name='graphs_view'),
re_path(r'^fitness-progress/$',views.fitnessmetric_view,name='fitnessmetric_view'),
re_path(r'^fitness-progress/user/(?P<userid>\d+)/$',views.fitnessmetric_view,name='fitnessmetric_view'),
re_path(r'^fitness-progress/user/(?P<userid>\d+)/(?P<mode>\w+.*)/$',views.fitnessmetric_view,name='fitnessmetric_view'),
#re_path(r'^fitness-progress/$',views.fitnessmetric_view,name='fitnessmetric_view'),
#re_path(r'^fitness-progress/user/(?P<userid>\d+)/$',views.fitnessmetric_view,name='fitnessmetric_view'),
#re_path(r'^fitness-progress/user/(?P<userid>\d+)/(?P<mode>\w+.*)/$',views.fitnessmetric_view,name='fitnessmetric_view'),
re_path(r'^createmarkerworkouts/user/(?P<userid>\d+)/$',views.create_marker_workouts_view,
name='create_marker_workouts_view'),
re_path(r'^createmarkerworkouts/$',views.create_marker_workouts_view,

View File

@@ -1484,63 +1484,6 @@ def planrequired_view(request):
return HttpResponseRedirect(reverse('paidplans_view'))
@user_passes_test(isplanmember,login_url="/rowers/paidplans",
message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None)
@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
def fitnessmetric_view(request,userid=0,mode='rower',
startdate=timezone.now()-timezone.timedelta(days=365),
enddate=timezone.now()):
therower = getrequestrower(request,userid=userid)
theuser = therower.user
if request.method == 'POST':
form = FitnessMetricForm(request.POST)
if form.is_valid():
startdate = form.cleaned_data['startdate']
enddate = form.cleaned_data['enddate']
mode = form.cleaned_data['mode']
else:
form = FitnessMetricForm()
fitnessmetrics = PowerTimeFitnessMetric.objects.filter(
user=theuser,
workoutmode=mode,
date__gte=startdate,
date__lte=enddate)
script,thediv = fitnessmetric_chart(
fitnessmetrics,theuser,
workoutmode=mode,startdate=startdate,
enddate=enddate,
)
breadcrumbs = [
{
'url':'/rowers/analysis',
'name':'Analysis'
},
{
'url':reverse('fitnessmetric_view'),
'name': 'Power Progress'
}
]
return render(request,'fitnessmetric.html',
{
'rower':therower,
'active':'nav-analysis',
'chartscript':script,
'breadcrumbs':breadcrumbs,
'the_div':thediv,
'mode':mode,
'form':form,
})
@user_passes_test(ispromember, login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",