instroke interactive as much polars as works
This commit is contained in:
@@ -1177,440 +1177,6 @@ def interactive_agegroup_plot(df, distance=2000, duration=None,
|
|||||||
|
|
||||||
return script, div
|
return script, div
|
||||||
|
|
||||||
|
|
||||||
def interactive_cpchart(rower, thedistances, thesecs, theavpower,
|
|
||||||
theworkouts, promember=0,
|
|
||||||
wcpower=[], wcdurations=[]):
|
|
||||||
|
|
||||||
message = 0
|
|
||||||
# plot tools
|
|
||||||
if (promember == 1):
|
|
||||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
|
||||||
else: # pragma: no cover
|
|
||||||
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
|
||||||
|
|
||||||
x_axis_type = 'log'
|
|
||||||
|
|
||||||
thesecs = pd.Series(thesecs)
|
|
||||||
|
|
||||||
velo = thedistances/thesecs
|
|
||||||
p = pd.Series(500./velo)
|
|
||||||
|
|
||||||
p2 = p.fillna(method='ffill').apply(lambda x: timedeltaconv(x))
|
|
||||||
|
|
||||||
source = ColumnDataSource(
|
|
||||||
data=dict(
|
|
||||||
dist=thedistances,
|
|
||||||
duration=thesecs,
|
|
||||||
spm=0*theavpower,
|
|
||||||
tim=niceformat(
|
|
||||||
thesecs.fillna(method='ffill').apply(
|
|
||||||
lambda x: timedeltaconv(x))
|
|
||||||
),
|
|
||||||
|
|
||||||
power=theavpower,
|
|
||||||
fpace=nicepaceformat(p2),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# fitting the data to Paul
|
|
||||||
if len(thedistances) >= 2:
|
|
||||||
paulslope, paulintercept, r, p, stderr = linregress(
|
|
||||||
np.log10(thedistances), p)
|
|
||||||
else: # pragma: no cover
|
|
||||||
paulslope = 5.0/np.log10(2.0)
|
|
||||||
paulintercept = p[0]-paulslope*np.log10(thedistances[0])
|
|
||||||
|
|
||||||
fitx = pd.Series(np.arange(100)*2*max(np.log10(thedistances))/100.)
|
|
||||||
|
|
||||||
fitp = paulslope*fitx+paulintercept
|
|
||||||
|
|
||||||
fitvelo = 500./fitp
|
|
||||||
fitpower = 2.8*(fitvelo**3)
|
|
||||||
fitt = 10**fitx/fitvelo
|
|
||||||
fitp2 = fitp.fillna(method='ffill').apply(lambda x: timedeltaconv(x))
|
|
||||||
|
|
||||||
sourcepaul = ColumnDataSource(
|
|
||||||
data=dict(
|
|
||||||
dist=10**fitx,
|
|
||||||
duration=fitt,
|
|
||||||
power=fitpower,
|
|
||||||
spm=0*fitpower,
|
|
||||||
tim=niceformat(
|
|
||||||
fitt.fillna(method='ffill').apply(lambda x: timedeltaconv(x))
|
|
||||||
),
|
|
||||||
fpace=nicepaceformat(fitp2),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def fitfunc(pars, x):
|
|
||||||
return pars[0] / (1+(x/pars[2])) + pars[1]/(1+(x/pars[3]))
|
|
||||||
|
|
||||||
def errfunc(pars, x, y):
|
|
||||||
return fitfunc(pars, x)-y
|
|
||||||
|
|
||||||
# p0 = [500,350,10,8000]
|
|
||||||
wcpower = pd.Series(wcpower, dtype='float')
|
|
||||||
wcdurations = pd.Series(wcdurations, dtype='float')
|
|
||||||
|
|
||||||
# fitting WC data to three parameter CP model
|
|
||||||
if len(wcdurations) >= 4:
|
|
||||||
p1wc, success = optimize.leastsq(errfunc, p0[:],
|
|
||||||
args=(wcdurations, wcpower))
|
|
||||||
else: # pragma: no cover
|
|
||||||
p1wc = None
|
|
||||||
|
|
||||||
# fitting the data to three parameter CP model
|
|
||||||
|
|
||||||
success = 0
|
|
||||||
p1 = p0
|
|
||||||
if len(thesecs) >= 4:
|
|
||||||
try:
|
|
||||||
p1, success = optimize.leastsq(
|
|
||||||
errfunc, p0[:], args=(thesecs, theavpower))
|
|
||||||
except (RuntimeError, RuntimeWarning): # pragma: no cover
|
|
||||||
factor = fitfunc(p0, thesecs.mean())/theavpower.mean()
|
|
||||||
p1 = [p0[0]/factor, p0[1]/factor, p0[2], p0[3]]
|
|
||||||
success = 0
|
|
||||||
else: # pragma: no cover
|
|
||||||
factor = fitfunc(p0, thesecs.mean())/theavpower.mean()
|
|
||||||
p1 = [p0[0]/factor, p0[1]/factor, p0[2], p0[3]]
|
|
||||||
success = 0
|
|
||||||
|
|
||||||
# Get stayer score
|
|
||||||
if success == 1: # pragma: no cover
|
|
||||||
power4min = fitfunc(p1, 240.)
|
|
||||||
power1h = fitfunc(p1, 3600.)
|
|
||||||
power10sec = fitfunc(p1, 10.)
|
|
||||||
r10sec4min = 100.*power10sec/power4min
|
|
||||||
r1h4min = 100.*power1h/power4min
|
|
||||||
|
|
||||||
combined = r1h4min-0.2*(r10sec4min-100)
|
|
||||||
|
|
||||||
dataset = pd.read_csv('static/stats/combined_set.csv')
|
|
||||||
|
|
||||||
stayerscore = int(percentileofscore(dataset['combined'], combined))
|
|
||||||
else:
|
|
||||||
stayerscore = None
|
|
||||||
|
|
||||||
fitt = pd.Series(10**(4*np.arange(100)/100.))
|
|
||||||
|
|
||||||
fitpower = fitfunc(p1, fitt)
|
|
||||||
if p1wc is not None:
|
|
||||||
fitpowerwc = 0.95*fitfunc(p1wc, fitt)
|
|
||||||
fitpowerexcellent = 0.7*fitfunc(p1wc, fitt)
|
|
||||||
fitpowergood = 0.6*fitfunc(p1wc, fitt)
|
|
||||||
fitpowerfair = 0.5*fitfunc(p1wc, fitt)
|
|
||||||
fitpoweraverage = 0.4*fitfunc(p1wc, fitt)
|
|
||||||
|
|
||||||
else: # pragma: no cover
|
|
||||||
fitpowerwc = 0*fitpower
|
|
||||||
fitpowerexcellent = 0*fitpower
|
|
||||||
fitpowergood = 0*fitpower
|
|
||||||
fitpowerfair = 0*fitpower
|
|
||||||
fitpoweraverage = 0*fitpower
|
|
||||||
|
|
||||||
message = ""
|
|
||||||
if len(fitpower[fitpower < 0]) > 0: # pragma: no cover
|
|
||||||
message = "CP model fit didn't give correct results"
|
|
||||||
|
|
||||||
fitvelo = (fitpower/2.8)**(1./3.)
|
|
||||||
fitdist = fitt*fitvelo
|
|
||||||
fitp = 500./fitvelo
|
|
||||||
fitp2 = fitp.fillna(method='ffill').apply(lambda x: timedeltaconv(x))
|
|
||||||
|
|
||||||
sourcecomplex = ColumnDataSource(
|
|
||||||
data=dict(
|
|
||||||
dist=fitdist,
|
|
||||||
duration=fitt,
|
|
||||||
tim=niceformat(
|
|
||||||
fitt.fillna(method='ffill').apply(lambda x: timedeltaconv(x))
|
|
||||||
),
|
|
||||||
spm=0*fitpower,
|
|
||||||
power=fitpower,
|
|
||||||
fitpowerwc=fitpowerwc,
|
|
||||||
fitpowerexcellent=fitpowerexcellent,
|
|
||||||
fitpowergood=fitpowergood,
|
|
||||||
fitpowerfair=fitpowerfair,
|
|
||||||
fitpoweraverage=fitpoweraverage,
|
|
||||||
fpace=nicepaceformat(fitp2),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# making the plot
|
|
||||||
plot = figure(tools=TOOLS, x_axis_type=x_axis_type,
|
|
||||||
width=900,
|
|
||||||
toolbar_location="above",
|
|
||||||
toolbar_sticky=False)
|
|
||||||
|
|
||||||
# add watermark
|
|
||||||
watermarkurl = "/static/img/logo7.png"
|
|
||||||
watermarkrange = Range1d(start=0, end=1)
|
|
||||||
watermarkalpha = 0.6
|
|
||||||
watermarky = 0.01
|
|
||||||
watermarkw = 184
|
|
||||||
watermarkh = 35
|
|
||||||
watermarkanchor = 'bottom_right'
|
|
||||||
plot.extra_y_ranges = {"watermark": watermarkrange}
|
|
||||||
#plot.sizing_mode = 'scale_both'
|
|
||||||
|
|
||||||
plot.image_url([watermarkurl], 1.8*max(thesecs), watermarky,
|
|
||||||
watermarkw, watermarkh,
|
|
||||||
global_alpha=watermarkalpha,
|
|
||||||
w_units='screen',
|
|
||||||
h_units='screen',
|
|
||||||
anchor=watermarkanchor,
|
|
||||||
dilate=True,
|
|
||||||
y_range_name="watermark",
|
|
||||||
)
|
|
||||||
|
|
||||||
plot.circle('duration', 'power', source=source, fill_color='red', size=15,
|
|
||||||
legend_label='Power')
|
|
||||||
plot.xaxis.axis_label = "Duration (seconds)"
|
|
||||||
plot.yaxis.axis_label = "Power (W)"
|
|
||||||
|
|
||||||
if stayerscore is not None: # pragma: no cover
|
|
||||||
plot.add_layout(
|
|
||||||
Label(x=100, y=100, x_units='screen', y_units='screen',
|
|
||||||
text='Stayer Score '+str(stayerscore)+'%',
|
|
||||||
background_fill_alpha=0.7,
|
|
||||||
background_fill_color='white',
|
|
||||||
text_color='black')
|
|
||||||
)
|
|
||||||
# plot.add_layout(
|
|
||||||
# Label(x=100,y=120,x_units='screen',y_units='screen',
|
|
||||||
# text='Stayer Score (6min) '+str(stayerscore2)+'%',
|
|
||||||
# background_fill_alpha=0.7,
|
|
||||||
# background_fill_color='white',
|
|
||||||
# text_color='black')
|
|
||||||
# )
|
|
||||||
|
|
||||||
cpdata = dataprep.fetchcperg(rower, theworkouts)
|
|
||||||
|
|
||||||
if cpdata.empty: # pragma: no cover
|
|
||||||
message = 'Calculations are running in the background. Please refresh this page to see updated results'
|
|
||||||
return ['', '', paulslope, paulintercept, p1, message, p1wc]
|
|
||||||
|
|
||||||
velo = cpdata['distance']/cpdata['delta']
|
|
||||||
|
|
||||||
p = 500./velo
|
|
||||||
|
|
||||||
p2 = p.fillna(method='ffill').apply(lambda x: timedeltaconv(x))
|
|
||||||
|
|
||||||
source2 = ColumnDataSource(
|
|
||||||
data=dict(
|
|
||||||
duration=cpdata['delta'],
|
|
||||||
power=cpdata['cp'],
|
|
||||||
tim=niceformat(
|
|
||||||
cpdata['delta'].fillna(method='ffill').apply(
|
|
||||||
lambda x: timedeltaconv(x))
|
|
||||||
),
|
|
||||||
dist=cpdata['distance'],
|
|
||||||
pace=nicepaceformat(p2),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
plot.circle('duration', 'power', source=source2,
|
|
||||||
fill_color='blue', size=3,
|
|
||||||
legend_label='Power from segments')
|
|
||||||
|
|
||||||
hover = plot.select(dict(type=HoverTool))
|
|
||||||
|
|
||||||
hover.tooltips = OrderedDict([
|
|
||||||
('Duration ', '@tim'),
|
|
||||||
('Power (W)', '@power{int}'),
|
|
||||||
('Distance (m)', '@dist{int}'),
|
|
||||||
('Pace (/500m)', '@fpace'),
|
|
||||||
])
|
|
||||||
|
|
||||||
hover.mode = 'mouse'
|
|
||||||
|
|
||||||
plot.y_range = Range1d(0, 1.5*max(theavpower))
|
|
||||||
plot.x_range = Range1d(1, 2*max(thesecs))
|
|
||||||
plot.legend.orientation = "vertical"
|
|
||||||
|
|
||||||
plot.line('duration', 'power', source=sourcepaul,
|
|
||||||
legend_label="Paul's Law")
|
|
||||||
plot.line('duration', 'power', source=sourcecomplex, legend_label="CP Model",
|
|
||||||
color='green')
|
|
||||||
if p1wc is not None:
|
|
||||||
plot.line('duration', 'fitpowerwc', source=sourcecomplex,
|
|
||||||
legend_label="World Class",
|
|
||||||
color='Maroon', line_dash='dotted')
|
|
||||||
|
|
||||||
plot.line('duration', 'fitpowerexcellent', source=sourcecomplex,
|
|
||||||
legend_label="90% percentile",
|
|
||||||
color='Purple', line_dash='dotted')
|
|
||||||
|
|
||||||
plot.line('duration', 'fitpowergood', source=sourcecomplex,
|
|
||||||
legend_label="75% percentile",
|
|
||||||
color='Olive', line_dash='dotted')
|
|
||||||
|
|
||||||
plot.line('duration', 'fitpowerfair', source=sourcecomplex,
|
|
||||||
legend_label="50% percentile",
|
|
||||||
color='Gray', line_dash='dotted')
|
|
||||||
|
|
||||||
plot.line('duration', 'fitpoweraverage', source=sourcecomplex,
|
|
||||||
legend_label="25% percentile",
|
|
||||||
color='SkyBlue', line_dash='dotted')
|
|
||||||
|
|
||||||
script, div = components(plot)
|
|
||||||
|
|
||||||
return [script, div, paulslope, paulintercept, p1, message, p1wc]
|
|
||||||
|
|
||||||
|
|
||||||
def interactive_windchart(id=0, promember=0):
|
|
||||||
# check if valid ID exists (workout exists)
|
|
||||||
row = Workout.objects.get(id=id)
|
|
||||||
# g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime")
|
|
||||||
|
|
||||||
f1 = row.csvfilename
|
|
||||||
|
|
||||||
# create interactive plot
|
|
||||||
plot = figure(width=400, height=300)
|
|
||||||
|
|
||||||
# get user
|
|
||||||
# u = User.objects.get(id=row.user.id)
|
|
||||||
r = row.user
|
|
||||||
|
|
||||||
rr = rrower(hrmax=r.max, hrut2=r.ut2,
|
|
||||||
hrut1=r.ut1, hrat=r.at,
|
|
||||||
hrtr=r.tr, hran=r.an, ftp=r.ftp)
|
|
||||||
|
|
||||||
rowdata = rdata(f1, rower=rr)
|
|
||||||
if rowdata == 0: # pragma: no cover
|
|
||||||
return 0
|
|
||||||
|
|
||||||
try:
|
|
||||||
dist = rowdata.df.loc[:, 'cum_dist']
|
|
||||||
except KeyError:
|
|
||||||
return ['', 'No Data Found']
|
|
||||||
|
|
||||||
try: # pragma: no cover
|
|
||||||
vwind = rowdata.df.loc[:, 'vwind']
|
|
||||||
winddirection = rowdata.df.loc[:, 'winddirection']
|
|
||||||
bearing = rowdata.df.loc[:, 'bearing']
|
|
||||||
except KeyError:
|
|
||||||
rowdata.add_wind(0, 0)
|
|
||||||
rowdata.add_bearing()
|
|
||||||
vwind = rowdata.df.loc[:, 'vwind']
|
|
||||||
winddirection = rowdata.df.loc[:, 'winddirection']
|
|
||||||
bearing = rowdata.df.loc[:, 'winddirection']
|
|
||||||
rowdata.write_csv(f1, gzip=True)
|
|
||||||
dataprep.update_strokedata(id, rowdata.df)
|
|
||||||
|
|
||||||
winddirection = winddirection % 360
|
|
||||||
winddirection = (winddirection + 360) % 360
|
|
||||||
|
|
||||||
tw = tailwind(bearing, vwind, 1.0*winddirection)
|
|
||||||
|
|
||||||
source = ColumnDataSource(
|
|
||||||
data=dict(
|
|
||||||
dist=dist,
|
|
||||||
vwind=vwind,
|
|
||||||
tw=tw,
|
|
||||||
winddirection=winddirection,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# plot tools
|
|
||||||
if (promember == 1):
|
|
||||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,crosshair'
|
|
||||||
else: # pragma: no cover
|
|
||||||
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair'
|
|
||||||
|
|
||||||
# making the plot
|
|
||||||
plot = figure(tools=TOOLS, width=400, height=500,
|
|
||||||
# toolbar_location="below",
|
|
||||||
toolbar_sticky=False,
|
|
||||||
)
|
|
||||||
plot.line('dist', 'vwind', source=source, legend_label="Wind Speed (m/s)")
|
|
||||||
plot.line('dist', 'tw', source=source,
|
|
||||||
legend_label="Tail (+)/Head (-) Wind (m/s)", color='black')
|
|
||||||
try:
|
|
||||||
plot.title.text = row.name
|
|
||||||
except ValueError: # pragma: no cover
|
|
||||||
plot.title.text = ""
|
|
||||||
# plot.title.text_font_size="1.0em"
|
|
||||||
plot.title.text_font = "1.0em"
|
|
||||||
plot.xaxis.axis_label = "Distance (m)"
|
|
||||||
plot.yaxis.axis_label = "Wind Speed (m/s)"
|
|
||||||
plot.y_range = Range1d(-7, 7)
|
|
||||||
#plot.sizing_mode = 'stretch_both'
|
|
||||||
|
|
||||||
plot.extra_y_ranges = {"winddirection": Range1d(start=0, end=360)}
|
|
||||||
plot.line('dist', 'winddirection', source=source,
|
|
||||||
legend_label='Wind Direction', color="red",
|
|
||||||
y_range_name="winddirection")
|
|
||||||
plot.add_layout(LinearAxis(y_range_name="winddirection",
|
|
||||||
axis_label="Wind Direction (degree)"), 'right')
|
|
||||||
|
|
||||||
script, div = components(plot)
|
|
||||||
|
|
||||||
return [script, div]
|
|
||||||
|
|
||||||
|
|
||||||
def interactive_streamchart(id=0, promember=0):
|
|
||||||
# check if valid ID exists (workout exists)
|
|
||||||
row = Workout.objects.get(id=id)
|
|
||||||
# g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime")
|
|
||||||
|
|
||||||
f1 = row.csvfilename
|
|
||||||
|
|
||||||
# create interactive plot
|
|
||||||
plot = figure(width=400,
|
|
||||||
)
|
|
||||||
# get user
|
|
||||||
# u = User.objects.get(id=row.user.id)
|
|
||||||
r = row.user
|
|
||||||
|
|
||||||
rr = rrower(hrmax=r.max, hrut2=r.ut2,
|
|
||||||
hrut1=r.ut1, hrat=r.at,
|
|
||||||
hrtr=r.tr, hran=r.an, ftp=r.ftp)
|
|
||||||
|
|
||||||
rowdata = rdata(f1, rower=rr)
|
|
||||||
if rowdata == 0: # pragma: no cover
|
|
||||||
return "", "No Valid Data Available"
|
|
||||||
|
|
||||||
try:
|
|
||||||
dist = rowdata.df.loc[:, 'cum_dist']
|
|
||||||
except KeyError:
|
|
||||||
return ['', 'No Data found']
|
|
||||||
|
|
||||||
try:
|
|
||||||
vstream = rowdata.df.loc[:, 'vstream']
|
|
||||||
except KeyError:
|
|
||||||
rowdata.add_stream(0)
|
|
||||||
vstream = rowdata.df.loc[:, 'vstream']
|
|
||||||
rowdata.write_csv(f1, gzip=True)
|
|
||||||
dataprep.update_strokedata(id, rowdata.df)
|
|
||||||
|
|
||||||
# plot tools
|
|
||||||
if (promember == 1):
|
|
||||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,crosshair'
|
|
||||||
else: # pragma: no cover
|
|
||||||
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair'
|
|
||||||
|
|
||||||
# making the plot
|
|
||||||
plot = figure(tools=TOOLS, width=400, height=500,
|
|
||||||
# toolbar_location="below",
|
|
||||||
toolbar_sticky=False,
|
|
||||||
)
|
|
||||||
plot.line(dist, vstream, legend_label="River Stream Velocity (m/s)")
|
|
||||||
try:
|
|
||||||
plot.title.text = row.name
|
|
||||||
except ValueError: # pragma: no cover
|
|
||||||
plot.title.text = ""
|
|
||||||
plot.title.text_font_size = "1.0em"
|
|
||||||
plot.xaxis.axis_label = "Distance (m)"
|
|
||||||
plot.yaxis.axis_label = "River Current (m/s)"
|
|
||||||
plot.y_range = Range1d(-2, 2)
|
|
||||||
#plot.sizing_mode = 'stretch_both'
|
|
||||||
|
|
||||||
script, div = components(plot)
|
|
||||||
|
|
||||||
return [script, div]
|
|
||||||
|
|
||||||
def forcecurve_multi_interactive_chart(selected): # pragma: no cover
|
def forcecurve_multi_interactive_chart(selected): # pragma: no cover
|
||||||
ids = [analysis.id for analysis in selected]
|
ids = [analysis.id for analysis in selected]
|
||||||
workoutids = [analysis.workout.id for analysis in selected]
|
workoutids = [analysis.workout.id for analysis in selected]
|
||||||
@@ -1678,12 +1244,13 @@ def instroke_multi_interactive_chart(selected, *args, **kwargs): # pragma: no co
|
|||||||
maximum_values[analysis.metric] = mean_vals.max()
|
maximum_values[analysis.metric] = mean_vals.max()
|
||||||
xvals = np.arange(len(mean_vals))
|
xvals = np.arange(len(mean_vals))
|
||||||
|
|
||||||
data2 = pd.DataFrame({
|
data2 = pl.DataFrame({
|
||||||
'x': pd.Series(xvals),
|
'x': pl.Series(xvals),
|
||||||
'y': pd.Series(mean_vals),
|
'y': pl.Series(mean_vals),
|
||||||
|
|
||||||
})
|
})
|
||||||
data2['id'] = cntr
|
data2 = data2.with_columns((pl.lit(cntr)).alias("id"))
|
||||||
|
|
||||||
df2.append(data2)
|
df2.append(data2)
|
||||||
|
|
||||||
legendlabel = '{name} - {metric} - {workout}'.format(
|
legendlabel = '{name} - {metric} - {workout}'.format(
|
||||||
@@ -1704,9 +1271,9 @@ def instroke_multi_interactive_chart(selected, *args, **kwargs): # pragma: no co
|
|||||||
ytitle = 'Scaled'
|
ytitle = 'Scaled'
|
||||||
cntr = cntr+1
|
cntr = cntr+1
|
||||||
|
|
||||||
df2 = pd.concat(df2, axis=0)
|
df2 = pl.concat(df2)
|
||||||
|
|
||||||
data_dict = df2.to_dict("records")
|
data_dict = df2.to_dicts()
|
||||||
|
|
||||||
chart_data = {
|
chart_data = {
|
||||||
'title': '',
|
'title': '',
|
||||||
@@ -1725,24 +1292,25 @@ def instroke_interactive_chart(df,metric, workout, spm_min, spm_max,
|
|||||||
individual_curves,
|
individual_curves,
|
||||||
name='',notes=''): # pragma: no cover
|
name='',notes=''): # pragma: no cover
|
||||||
|
|
||||||
df_pos = (df+abs(df))/2.
|
|
||||||
df_min = -(-df+abs(-df))/2.
|
|
||||||
|
|
||||||
if df.empty:
|
if df.empty:
|
||||||
return "", "No data in selection"
|
return "", "No data in selection"
|
||||||
|
|
||||||
mean_vals = df.median().replace(0, np.nan)
|
|
||||||
q75 = df_pos.quantile(q=0.75).replace(0,np.nan)
|
|
||||||
q25 = df_pos.quantile(q=0.25).replace(0,np.nan)
|
|
||||||
q75min = df_min.quantile(q=0.75).replace(0,np.nan)
|
|
||||||
q25min = df_min.quantile(q=0.25).replace(0,np.nan)
|
|
||||||
|
|
||||||
|
df_pos = (df+abs(df))/2.
|
||||||
|
df_min = -(-df+abs(-df))/2.
|
||||||
|
|
||||||
|
|
||||||
|
mean_vals = df.median().replace(0, np.nan)
|
||||||
|
q75 = df_pos.quantile(q = 0.75).replace(0, np.nan)
|
||||||
|
q25 = df_pos.quantile(q=0.25).replace(0, np.nan)
|
||||||
|
q75min = df_min.quantile(q=0.75).replace(0, np.nan)
|
||||||
|
q25min = df_min.quantile(q=0.25).replace(0, np.nan)
|
||||||
|
|
||||||
mean_vals = mean_vals.interpolate()
|
mean_vals = mean_vals.interpolate()
|
||||||
|
|
||||||
xvals = np.arange(len(mean_vals))
|
xvals = np.arange(len(mean_vals))
|
||||||
|
|
||||||
df_plot = pd.DataFrame({
|
df_plot = pl.DataFrame({
|
||||||
'x':xvals,
|
'x':xvals,
|
||||||
'median':mean_vals,
|
'median':mean_vals,
|
||||||
'high':q75,
|
'high':q75,
|
||||||
@@ -1751,14 +1319,17 @@ def instroke_interactive_chart(df,metric, workout, spm_min, spm_max,
|
|||||||
'low 2': q25,
|
'low 2': q25,
|
||||||
})
|
})
|
||||||
|
|
||||||
df_plot['high'].update(df_plot.pop('high 2'))
|
df_plot = df_plot.with_columns(
|
||||||
df_plot['low'].update(df_plot.pop('low 2'))
|
pl.coalesce(["high", "high 2"]).alias("high")
|
||||||
try:
|
)
|
||||||
df_plot.interpolate(axis=1,inplace=True)
|
|
||||||
except TypeError:
|
df_plot = df_plot.with_columns(
|
||||||
pass
|
pl.coalesce("low", "low 2").alias("low")
|
||||||
|
)
|
||||||
|
|
||||||
|
df_plot = df_plot.drop(["high 2", "low 2"])
|
||||||
|
df_plot = df_plot.drop_nulls()
|
||||||
|
|
||||||
|
|
||||||
if metric == 'boat accelerator curve':
|
if metric == 'boat accelerator curve':
|
||||||
ytitle = "Boat acceleration (m/s^2)"
|
ytitle = "Boat acceleration (m/s^2)"
|
||||||
elif metric == 'instroke boat speed':
|
elif metric == 'instroke boat speed':
|
||||||
@@ -1771,7 +1342,7 @@ def instroke_interactive_chart(df,metric, workout, spm_min, spm_max,
|
|||||||
|
|
||||||
|
|
||||||
lines_dict = df.to_dict("records")
|
lines_dict = df.to_dict("records")
|
||||||
data_dict = df_plot.to_dict("records")
|
data_dict = df_plot.to_dicts()
|
||||||
|
|
||||||
chart_data = {
|
chart_data = {
|
||||||
'lines': lines_dict,
|
'lines': lines_dict,
|
||||||
@@ -1790,7 +1361,6 @@ def instroke_interactive_chart(df,metric, workout, spm_min, spm_max,
|
|||||||
'analysis_name': name,
|
'analysis_name': name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
script, div = get_chart("/instroke", chart_data, debug=False)
|
script, div = get_chart("/instroke", chart_data, debug=False)
|
||||||
|
|
||||||
return script, div
|
return script, div
|
||||||
|
|||||||
@@ -1523,19 +1523,6 @@ def otwcp_toadmin_view(request, theuser=0,
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
def agegroupcpview(request, age, normalize=0, userid=0):
|
|
||||||
script, div = interactive_agegroupcpchart(age, normalized=normalize)
|
|
||||||
|
|
||||||
response = render(request, 'agegroupcp.html',
|
|
||||||
{
|
|
||||||
'active': 'nav-analysis',
|
|
||||||
'interactiveplot': script,
|
|
||||||
'the_div': div,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
def agegrouprecordview(request, sex='male', weightcategory='hwt',
|
def agegrouprecordview(request, sex='male', weightcategory='hwt',
|
||||||
distance=2000, duration=None):
|
distance=2000, duration=None):
|
||||||
|
|||||||
Reference in New Issue
Block a user