From 394d80d040ceda53212c3b0f4c19ded97dd9b0b2 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 11 Jan 2021 20:43:37 +0100 Subject: [PATCH] a few more tests and removing old code --- rowers/interactiveplots.py | 420 -------------------------------- rowers/tests/test_analysis.py | 28 ++- rowers/tests/test_unit_tests.py | 16 +- rowers/tests/test_units.py | 7 +- rowers/urls.py | 6 +- rowers/views/analysisviews.py | 57 ----- 6 files changed, 47 insertions(+), 487 deletions(-) diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 51fbd38c..8e5287cf 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -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) diff --git a/rowers/tests/test_analysis.py b/rowers/tests/test_analysis.py index a4527159..e7696316 100644 --- a/rowers/tests/test_analysis.py +++ b/rowers/tests/test_analysis.py @@ -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) diff --git a/rowers/tests/test_unit_tests.py b/rowers/tests/test_unit_tests.py index 8b5db9f6..c1e2c9f3 100644 --- a/rowers/tests/test_unit_tests.py +++ b/rowers/tests/test_unit_tests.py @@ -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) diff --git a/rowers/tests/test_units.py b/rowers/tests/test_units.py index 544e7e8c..98ceba85 100644 --- a/rowers/tests/test_units.py +++ b/rowers/tests/test_units.py @@ -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: diff --git a/rowers/urls.py b/rowers/urls.py index 15f336fc..c7525dcd 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -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\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\d+)/$',views.fitnessmetric_view,name='fitnessmetric_view'), - re_path(r'^fitness-progress/user/(?P\d+)/(?P\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\d+)/$',views.fitnessmetric_view,name='fitnessmetric_view'), + #re_path(r'^fitness-progress/user/(?P\d+)/(?P\w+.*)/$',views.fitnessmetric_view,name='fitnessmetric_view'), re_path(r'^createmarkerworkouts/user/(?P\d+)/$',views.create_marker_workouts_view, name='create_marker_workouts_view'), re_path(r'^createmarkerworkouts/$',views.create_marker_workouts_view, diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py index 02aebe95..1f641793 100644 --- a/rowers/views/analysisviews.py +++ b/rowers/views/analysisviews.py @@ -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",