From 8a0518d7eb160eb48877037823b95df05cb04e6a Mon Sep 17 00:00:00 2001 From: sanderroosendaal Date: Thu, 3 Nov 2016 10:26:59 +0100 Subject: [PATCH] All Interactive plots now use the dataprep functions --- rowers/dataprep.py | 49 +++- rowers/interactiveplots.py | 318 ++++++-------------------- rowers/templates/biginteractive1.html | 2 + rowers/templates/otwinteractive.html | 4 +- 4 files changed, 125 insertions(+), 248 deletions(-) diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 5d841ba9..353a4f86 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -79,7 +79,7 @@ def getrowdata(id=0): return rowdata,row -def dataprep(rowdatadf): +def dataprep(rowdatadf,bands=False,barchart=False,otwpower=False): rowdatadf.set_index([range(len(rowdatadf))],inplace=True) t = rowdatadf.ix[:,'TimeStamp (sec)'] t = pd.Series(t-rowdatadf.ix[0,'TimeStamp (sec)']) @@ -120,6 +120,9 @@ def dataprep(rowdatadf): driveenergy = drivelength*averageforce*4.44822 distance = rowdatadf.ix[:,'cum_dist'] + + + data = DataFrame( dict( time = t2, @@ -137,8 +140,50 @@ def dataprep(rowdatadf): drivelength=drivelength, peakforce=peakforce, distance=distance, - drivespeed=drivespeed + drivespeed=drivespeed, ) ) + if bands: + # HR bands + data['hr_ut2'] = rowdatadf.ix[:,'hr_ut2'] + data['hr_ut1'] = rowdatadf.ix[:,'hr_ut1'] + data['hr_at'] = rowdatadf.ix[:,'hr_at'] + data['hr_tr'] = rowdatadf.ix[:,'hr_tr'] + data['hr_an'] = rowdatadf.ix[:,'hr_an'] + data['hr_max'] = rowdatadf.ix[:,'hr_max'] + data['hr_bottom'] = 0.0*data['hr'] + + if barchart: + # time increments for bar chart + time_increments = rowdatadf.ix[:,' ElapsedTime (sec)'].diff() + time_increments[0] = time_increments[1] + time_increments = 0.5*time_increments+0.5*np.abs(time_increments) + x_right = (t2+time_increments.apply(lambda x:timedeltaconv(x))) + + data['x_right'] = x_right + + if otwpower: + try: + nowindpace = rowdatadf.ix[:,'nowindpace'] + except KeyError: + nowindpace = p + try: + equivergpower = rowdatadf.ix[:,'equivergpower'] + except KeyError: + equivergpower = 0*p+50. + + nowindpace = nowindpace.apply(lambda x: timedeltaconv(x)) + ergvelo = (equivergpower/2.8)**(1./3.) + + ergpace = 500./ergvelo + ergpace[ergpace == np.inf] = 240. + ergpace = ergpace.apply(lambda x: timedeltaconv(x)) + + data['ergpace'] = ergpace + data['nowindpace'] = nowindpace + data['equivergpower'] = equivergpower + data['fergpace'] = nicepaceformat(ergpace) + data['fnowindpace'] = nicepaceformat(nowindpace) + return data diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 32496072..07db34d1 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -322,7 +322,7 @@ def interactive_cpchart(thedistances,thesecs,theavpower, ('Duration ','@tim'), ('Power (W)','@power{int}'), ('Distance (m)','@dist{int}'), - ('Pace (/500m)','@pace'), + ('Pace (/500m)','@fpace'), ]) hover.mode = 'mouse' @@ -545,7 +545,7 @@ def interactive_chart(id=0,promember=0): hover.tooltips = OrderedDict([ ('Time','@ftime'), ('Pace','@fpace'), - ('HR','@hr'), + ('HR','@hr{int}'), ('SPM','@spm{1.1}'), ('Distance','@cumdist{1.1}'), ]) @@ -782,9 +782,9 @@ def interactive_cum_flex_chart(theworkouts,promember=0, hover.tooltips = OrderedDict([ - ('Time','@time'), - ('Pace','@pace'), - ('HR','@hr'), + ('Time','@ftime'), + ('Pace','@fpace'), + ('HR','@hr{int}'), ('SPM','@spm{1.1}'), ('Power','@power{int}'), ]) @@ -1131,10 +1131,10 @@ def interactive_flex_chart2(id=0,promember=0, hover.tooltips = OrderedDict([ - ('Time','@time'), - ('Distance','@distance'), - ('Pace','@pace'), - ('HR','@hr'), + ('Time','@ftime'), + ('Distance','@distance{int}'), + ('Pace','@fpace'), + ('HR','@hr{int}'), ('SPM','@spm{1.1}'), ('Power','@power{int}'), ]) @@ -1258,41 +1258,10 @@ def interactive_bar_chart(id=0,promember=0): rowdata,row = dataprep.getrowdata(id=id) if rowdata == 0: return "","CSV Data File Not Found" - - t = rowdata.df.ix[:,'TimeStamp (sec)'] - t = t-rowdata.df.ix[0,'TimeStamp (sec)'] - row_index = rowdata.df.ix[:,' Stroke500mPace (sec/500m)'] > 3000 - rowdata.df.loc[row_index,' Stroke500mPace (sec/500m)'] = 3000. + rowdata = dataprep.dataprep(rowdata.df,bands=True,barchart=True) - p = rowdata.df.ix[:,' Stroke500mPace (sec/500m)'] - hr = rowdata.df.ix[:,' HRCur (bpm)'] - spm = rowdata.df.ix[:,' Cadence (stokes/min)'] - f = rowdata.df['TimeStamp (sec)'].diff().mean() - windowsize = 2*(int(10./(f)))+1 - if windowsize <= 3: - windowsize = 5 - - if windowsize > 3: - spm = savgol_filter(spm,windowsize,3) - rowdata.df[' Cadence (stokes/min)'] = spm - drivelength = rowdata.df[' DriveLength (meters)'] - if windowsize > 3: - drivelength = savgol_filter(drivelength,windowsize,3) - rowdata.df[' DriveLength (meters)'] = drivelength - - hr_ut2 = rowdata.df.ix[:,'hr_ut2'] - hr_ut1 = rowdata.df.ix[:,'hr_ut1'] - hr_at = rowdata.df.ix[:,'hr_at'] - hr_tr = rowdata.df.ix[:,'hr_tr'] - hr_an = rowdata.df.ix[:,'hr_an'] - hr_max = rowdata.df.ix[:,'hr_max'] - - # time increments for bar chart - time_increments = rowdata.df.ix[:,' ElapsedTime (sec)'].diff() - time_increments[0] = time_increments[1] - time_increments = 0.5*time_increments+0.5*np.abs(time_increments) # Add hover to this comma-separated string and see what changes @@ -1301,35 +1270,15 @@ def interactive_bar_chart(id=0,promember=0): else: TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' - t2 = t.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - p2 = p.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - source = ColumnDataSource( - data = dict( - x=t2, - x_right = (t+time_increments).fillna(method='ffill').apply(lambda x:timedeltaconv(x)), - hr=hr, - hr_ut2=hr_ut2, - hr_ut1=hr_ut1, - hr_at=hr_at, - hr_tr=hr_tr, - hr_an=hr_an, - hr_max=hr_max, - hr_bottom = 0.0*hr, - y2=p2, - tf = niceformat(t2), - pace = nicepaceformat(p2), - heartrate = hr, - spmc=np.rint(10*spm)/10., - spm=spm, - ) + rowdata ) + plot = Figure(x_axis_type="datetime",y_axis_type="datetime", toolbar_sticky=False, plot_width=920, -# toolbar_location="above", tools=TOOLS) plot.title.text = row.name plot.title.text_font_size=value("1.0em") @@ -1363,38 +1312,38 @@ def interactive_bar_chart(id=0,promember=0): hover.tooltips = OrderedDict([ - ('Time','@tf'), - ('Pace','@pace'), - ('HR','@heartrate'), - ('SPM','@spmc{1.1}'), + ('Time','@ftime'), + ('Pace','@fpace'), + ('HR','@hr{int}'), + ('SPM','@spm{1.1}'), ]) hover.mode = 'mouse' plot.extra_y_ranges = {"hr": Range1d(start=100,end=200)} - plot.quad(left='x',top='hr_ut2',bottom='hr_bottom', + plot.quad(left='time',top='hr_ut2',bottom='hr_bottom', right='x_right',source=source,color="gray", y_range_name="hr", legend=" 3: - spm1 = savgol_filter(spm1,windowsize,3) - rowdata1.df[' Cadence (stokes/min)'] = spm1 - drivelength1 = rowdata1.df[' DriveLength (meters)'] - if windowsize > 3: - drivelength1 = savgol_filter(drivelength1,windowsize,3) - rowdata1.df[' DriveLength (meters)'] = drivelength1 - - drivelength2 = rowdata2.df[' DriveLength (meters)'] - if windowsize > 3: - drivelength2 = savgol_filter(drivelength2,windowsize,3) - rowdata2.df[' DriveLength (meters)'] = drivelength2 - - - f = rowdata2.df['TimeStamp (sec)'].diff().mean() - windowsize = 2*(int(10./(f)))+1 - if windowsize <= 3: - windowsize = 5 - - if windowsize > 3: - spm2 = savgol_filter(spm2,windowsize,3) - rowdata2.df[' Cadence (stokes/min)'] = spm2 - drivelength2 = rowdata2.df[' DriveLength (meters)'] - if windowsize > 3: - drivelength2 = savgol_filter(drivelength2,windowsize,3) - rowdata2.df[' DriveLength (meters)'] = drivelength2 - - rowdata1.df['drivespeed'] = drivelength1/rowdata1.df[' DriveTime (ms)']*1.0e3 - rowdata2.df['drivespeed'] = drivelength2/rowdata2.df[' DriveTime (ms)']*1.0e3 + rowdata1 = dataprep.dataprep(rowdata1.df) + rowdata2 = dataprep.dataprep(rowdata2.df) - x1 = rowdata1.df.ix[:,csvcolumns[xparam]] - x2 = rowdata2.df.ix[:,csvcolumns[xparam]] - y1 = rowdata1.df.ix[:,csvcolumns[yparam]] - y2 = rowdata2.df.ix[:,csvcolumns[yparam]] + x1 = rowdata1.ix[:,xparam] + x2 = rowdata2.ix[:,xparam] + + y1 = rowdata1.ix[:,yparam] + y2 = rowdata2.ix[:,yparam] - if xparam=='time': - x1 = x1-x1[0] - x2 = x2-x2[0] - x1 = x1.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - x2 = x2.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - x_axis_type = 'linear' y_axis_type = 'linear' if xparam == 'time': @@ -1504,8 +1397,6 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm', if yparam == 'pace': y_axis_type = 'datetime' - y1 = y1.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - y2 = y2.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) ymax = 1.0e3*90 ymin = 1.0e3*180 @@ -1513,22 +1404,21 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm', ymax = 1.0e3*90 ymin = 1.0e3*210 - time1 = rowdata1.df.ix[:,csvcolumns['time']] - time2 = rowdata2.df.ix[:,csvcolumns['time']] + ftime1 = rowdata1.ix[:,'ftime'] + ftime2 = rowdata2.ix[:,'ftime'] - time1 = time1-time1[0] - time2 = time2-time2[0] - - hr1 = rowdata1.df.ix[:,csvcolumns['hr']] - hr2 = rowdata2.df.ix[:,csvcolumns['hr']] + hr1 = rowdata1.ix[:,'hr'] + hr2 = rowdata2.ix[:,'hr'] - pace1 = rowdata1.df.ix[:,csvcolumns['pace']] - pace2 = rowdata2.df.ix[:,csvcolumns['pace']] + fpace1 = rowdata1.ix[:,'fpace'] + fpace2 = rowdata2.ix[:,'fpace'] - distance1 = rowdata1.df.ix[:,csvcolumns['distance']] - distance2 = rowdata2.df.ix[:,csvcolumns['distance']] + distance1 = rowdata1.ix[:,'distance'] + distance2 = rowdata2.ix[:,'distance'] + spm1 = rowdata1.ix[:,'spm'] + spm2 = rowdata2.ix[:,'spm'] if (promember==1): TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' @@ -1536,36 +1426,29 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm', TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' - - source = ColumnDataSource( - data = dict( + data = pd.DataFrame( + dict( x1=x1, x2=x2, y1=y1, y2=y2, - time1=niceformat( - time1.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - ), - - time2=niceformat( - time2.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - ), - pace1=nicepaceformat( - pace1.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - ), - - pace2=nicepaceformat( - pace2.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - ), + ftime1=ftime1, + ftime2=ftime2, + fpace1=fpace1, + fpace2=fpace2, hr1 = hr1, hr2 = hr2, spm1 = spm1, spm2 = spm2, - spm1c=np.rint(10*spm1)/10., - spm2c=np.rint(10*spm2)/10., distance1=distance1, distance2=distance2, ) + ).dropna() + + + + source = ColumnDataSource( + data ) @@ -1610,20 +1493,20 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm', minutes = ["%M"] ) - plot.y_range = Range1d(ymin,ymax) + #plot.y_range = Range1d(ymin,ymax) hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ - ('time1','@time1'), - ('time2','@time2'), - ('pace1','@pace1'), - ('pace2','@pace2'), + ('time1','@ftime1'), + ('time2','@ftime2'), + ('pace1','@fpace1'), + ('pace2','@fpace2'), ('hr1','@hr1'), ('hr2','@hr2'), - ('spm1','@spm1c{1.1}'), - ('spm2','@spm2c{1.1}'), + ('spm1','@spm1{1.1}'), + ('spm2','@spm2{1.1}'), ('distance1','@distance1{5}'), ('distance2','@distance2{5}'), ]) @@ -1639,53 +1522,9 @@ def interactive_otw_advanced_pace_chart(id=0,promember=0): rowdata,row = dataprep.getrowdata(id=id) if rowdata == 0: return "","CSV Data File Not Found" + + rowdata = dataprep.dataprep(rowdata.df,otwpower=True) - t = rowdata.df.ix[:,'TimeStamp (sec)'] - t = t-rowdata.df.ix[0,'TimeStamp (sec)'] - - - row_index = rowdata.df.ix[:,' Stroke500mPace (sec/500m)'] > 3000 - rowdata.df.loc[row_index,' Stroke500mPace (sec/500m)'] = 3000. - - - p = rowdata.df.ix[:,' Stroke500mPace (sec/500m)'] - try: - nowindpace = rowdata.df.ix[:,'nowindpace'] - except KeyError: - nowindpace = p - try: - equivergpower = rowdata.df.ix[:,'equivergpower'] - except KeyError: - equivergpower = 0*p+50. - - ergvelo = (equivergpower/2.8)**(1./3.) - - # ergvelo = stravastuff.ewmovingaverage(ergvelo,25) - - ergpace = 500./ergvelo - ergpace[ergpace == np.inf] = 240. - - hr = rowdata.df.ix[:,' HRCur (bpm)'] - spm = rowdata.df.ix[:,' Cadence (stokes/min)'] - - f = rowdata.df['TimeStamp (sec)'].diff().mean() - windowsize = 2*(int(10./(f)))+1 - if windowsize <= 3: - windowsize = 5 - - if windowsize > 3: - spm = savgol_filter(spm,windowsize,3) - rowdata.df[' Cadence (stokes/min)'] = spm - drivelength = rowdata.df[' DriveLength (meters)'] - if windowsize > 3: - drivelength = savgol_filter(drivelength,windowsize,3) - rowdata.df[' DriveLength (meters)'] = drivelength - - t2 = t.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - p2 = p.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - nowindp2 = nowindpace.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - ergpace2 = ergpace.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - # Add hover to this comma-separated string and see what changes if (promember==1): TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' @@ -1693,21 +1532,10 @@ def interactive_otw_advanced_pace_chart(id=0,promember=0): TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' source = ColumnDataSource( - data = dict( - x=t2, - p=p2, - nowindp2 = nowindp2, - ergpace2 = ergpace2, - tf = niceformat(t2), - pace = nicepaceformat(p2), - ergpace = nicepaceformat(ergpace2), - nowindpace = nicepaceformat(nowindp2), - heartrate = hr, - spm=spm, - spmc=np.rint(10*spm)/10., - ) + rowdata ) + plot = Figure(x_axis_type="datetime",y_axis_type="datetime", tools=TOOLS, plot_width=920, @@ -1738,17 +1566,17 @@ def interactive_otw_advanced_pace_chart(id=0,promember=0): hover = plot.select(dict(type=HoverTool)) - plot.line('x','p',source=source,legend="Pace",color="black") - plot.line('x','nowindp2',source=source,legend="Corrected Pace",color="red") - plot.line('x','ergpace2',source=source,legend="Equivalent Erg Pace",color="blue") + plot.line('time','pace',source=source,legend="Pace",color="black") + plot.line('time','nowindpace',source=source,legend="Corrected Pace",color="red") + plot.line('time','ergpace',source=source,legend="Equivalent Erg Pace",color="blue") hover.tooltips = OrderedDict([ - ('Time','@tf'), - ('Pace','@pace'), - ('Corrected Pace','@nowindpace'), - ('Equiv. Erg Pace','@ergpace'), - ('HR','@heartrate'), - ('SPM','@spmc{1.1}'), + ('Time','@ftime'), + ('Pace','@fpace'), + ('Corrected Pace','@fnowindpace'), + ('Equiv. Erg Pace','@fergpace'), + ('HR','@hr{int}'), + ('SPM','@spm{1.1}'), ]) hover.mode = 'mouse' diff --git a/rowers/templates/biginteractive1.html b/rowers/templates/biginteractive1.html index 6b7c1c61..3613da98 100644 --- a/rowers/templates/biginteractive1.html +++ b/rowers/templates/biginteractive1.html @@ -53,7 +53,9 @@ {% endif %} +
{{ the_div|safe }} +
diff --git a/rowers/templates/otwinteractive.html b/rowers/templates/otwinteractive.html index 2f2b4e2c..66159c5b 100644 --- a/rowers/templates/otwinteractive.html +++ b/rowers/templates/otwinteractive.html @@ -61,11 +61,13 @@ OTW Power {% endif %} + +
-
{{ the_div|safe }}
+

Notes