All Interactive plots now use the dataprep functions
This commit is contained in:
@@ -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="<UT2")
|
||||
plot.quad(left='x',top='hr_ut1',bottom='hr_bottom',
|
||||
plot.quad(left='time',top='hr_ut1',bottom='hr_bottom',
|
||||
right='x_right',source=source,color="tan",
|
||||
y_range_name="hr", legend="UT2")
|
||||
plot.quad(left='x',top='hr_at',bottom='hr_bottom',
|
||||
plot.quad(left='time',top='hr_at',bottom='hr_bottom',
|
||||
right='x_right',source=source,color="green",
|
||||
y_range_name="hr", legend="UT1")
|
||||
plot.quad(left='x',top='hr_tr',bottom='hr_bottom',
|
||||
plot.quad(left='time',top='hr_tr',bottom='hr_bottom',
|
||||
right='x_right',source=source,color="blue",
|
||||
y_range_name="hr", legend="AT")
|
||||
plot.quad(left='x',top='hr_an',bottom='hr_bottom',
|
||||
plot.quad(left='time',top='hr_an',bottom='hr_bottom',
|
||||
right='x_right',source=source,color="violet",
|
||||
y_range_name="hr", legend="TR")
|
||||
plot.quad(left='x',top='hr_max',bottom='hr_bottom',
|
||||
plot.quad(left='time',top='hr_max',bottom='hr_bottom',
|
||||
right='x_right',source=source,color="red",
|
||||
y_range_name="hr", legend="AN")
|
||||
|
||||
|
||||
plot.add_layout(LinearAxis(y_range_name="hr",axis_label="HR"),'right')
|
||||
|
||||
plot.line('x','y2',source=source,legend="Pace",color="black")
|
||||
plot.line('time','pace',source=source,legend="Pace",color="black")
|
||||
|
||||
|
||||
script, div = components(plot)
|
||||
@@ -1405,19 +1354,6 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm',
|
||||
promember=0,plottype='line'):
|
||||
|
||||
|
||||
csvcolumns = {
|
||||
'time': 'TimeStamp (sec)',
|
||||
'distance': 'cum_dist',
|
||||
'hr': ' HRCur (bpm)',
|
||||
'spm': ' Cadence (stokes/min)',
|
||||
'pace': ' Stroke500mPace (sec/500m)',
|
||||
'power': ' Power (watts)',
|
||||
'averageforce': ' AverageDriveForce (lbs)',
|
||||
'drivelength': ' DriveLength (meters)',
|
||||
'peakforce': ' PeakDriveForce (lbs)',
|
||||
'driveenergy': 'driveenergy',
|
||||
'drivespeed': 'drivespeed',
|
||||
}
|
||||
|
||||
axlabels = {
|
||||
'time': 'Time',
|
||||
@@ -1436,67 +1372,24 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm',
|
||||
|
||||
# check if valid ID exists (workout exists)
|
||||
rowdata1,row1 = dataprep.getrowdata(id=id1)
|
||||
rowdata2,row2 = dataprep.getrowdata(id=id1)
|
||||
rowdata2,row2 = dataprep.getrowdata(id=id2)
|
||||
if rowdata1 == 0:
|
||||
return "","CSV Data File Not Found"
|
||||
|
||||
if rowdata2 == 0:
|
||||
return "","CSV Data File Not Found"
|
||||
|
||||
rowdata1.df['driveenergy'] = rowdata1.df[' DriveLength (meters)']*rowdata1.df[' AverageDriveForce (lbs)']*4.44822
|
||||
rowdata2.df['driveenergy'] = rowdata2.df[' DriveLength (meters)']*rowdata2.df[' AverageDriveForce (lbs)']*4.44822
|
||||
|
||||
spm1 = rowdata1.df.ix[:,csvcolumns['spm']]
|
||||
spm2 = rowdata2.df.ix[:,csvcolumns['spm']]
|
||||
|
||||
f = rowdata1.df['TimeStamp (sec)'].diff().mean()
|
||||
windowsize = 2*(int(10./(f)))+1
|
||||
if windowsize <= 3:
|
||||
windowsize = 5
|
||||
|
||||
if windowsize > 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'
|
||||
|
||||
Reference in New Issue
Block a user