from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage from rowingdata import rower as rrower from rowingdata import main as rmain from rowingdata import cumcpdata,histodata from rowingdata import rowingdata as rrdata from rowingdata import TCXParser,RowProParser,ErgDataParser from rowingdata import painsledDesktopParser,speedcoachParser,ErgStickParser from bokeh.plotting import figure, ColumnDataSource, Figure,curdoc from bokeh.models import CustomJS,Slider from bokeh.charts import Histogram from bokeh.resources import CDN,INLINE from bokeh.embed import components from bokeh.layouts import layout,widgetbox from bokeh.layouts import row as layoutrow from bokeh.layouts import column as layoutcolumn from bokeh.models import LinearAxis,LogAxis,Range1d,DatetimeTickFormatter,HoverTool from bokeh.io import output_file, show from bokeh.models import ( GMapPlot, GMapOptions, ColumnDataSource, Circle, DataRange1d, PanTool, WheelZoomTool, BoxSelectTool, SaveTool, ResizeTool, ResetTool, TapTool,CrosshairTool,BoxZoomTool, Span, ) #from bokeh.models.widgets import Slider, Select, TextInput from bokeh.core.properties import value from collections import OrderedDict from django.conf import settings import datetime import math import numpy as np import pandas as pd from pytz import timezone as tz,utc from django.utils.timezone import get_current_timezone from django.utils.timezone import activate activate(settings.TIME_ZONE) thetimezone = get_current_timezone() from scipy.stats import linregress from scipy import optimize from scipy.signal import savgol_filter import stravastuff def rdata(file,rower=rrower()): try: res = rrdata(file,rower=rower) except IOError: res = 0 return res def tailwind(bearing,vwind,winddir): """ Calculates head-on head/tailwind in direction of rowing positive numbers are tail wind """ b = np.radians(bearing) w = np.radians(winddir) vtail = -vwind*np.cos(w-b) return vtail def niceformat(values): out = [] for v in values: formattedv = v.strftime("%H:%M:%S") out.append(formattedv) return out def nicepaceformat(values): out = [] for v in values: formattedv = v.strftime("%M:%S.%f") out.append(formattedv[:-5]) return out def get_datetimes(seconds,tzinfo=0): out = [] for second in seconds: if (second<=0) or (second>1e9): days = 0 hours = 0 minutes=0 sec=0 microsecond = 0 elif math.isnan(second): days = 0 hours = 0 minutes=0 sec=0 microsecond = 0 else: days = int(second/(24.*3600.)) % (24*3600) hours = int((second-24.*3600.*days)/3600.) % 24 minutes = int((second-3600.*(hours+24.*days))/60.) % 60 sec = int(second-3600.*(hours+24.*days)-60.*minutes) % 60 microsecond = int(1.0e6*(second-3600.*(hours+24.*days)-60.*minutes-sec)) dt = datetime.datetime(2016,5,1,hours,minutes,sec,microsecond) if tzinfo: dt = thetimezone.localize(dt, is_dst=True) # this is ugly # dt = dt+datetime.timedelta(hours=1) out.append(dt) return out def interactive_histoall(theworkouts): TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' therows = [] for workout in theworkouts: f1 = workout.csvfilename rowdata = rdata(f1) if rowdata != 0: therows.append(rowdata) histopwr = histodata(therows) # throw out nans histopwr = histopwr[~np.isinf(histopwr)] histopwr = histopwr[histopwr > 25] plot = Figure(tools=TOOLS,plot_width=900, toolbar_sticky=False, toolbar_location="above" ) hist,edges = np.histogram(histopwr,bins=150) histsum = np.cumsum(hist) histsum = 100.*histsum/max(histsum) hist_norm = 100.*hist/float(hist.sum()) source = ColumnDataSource( data = dict( left = edges[:-1], right = edges[1:], histsum = histsum, hist_norm = hist_norm, ) ) # plot.quad(top='hist_norm',bottom=0,left=edges[:-1],right=edges[1:]) plot.quad(top='hist_norm',bottom=0,left='left',right='right',source=source) plot.xaxis.axis_label = "Power (W)" plot.yaxis.axis_label = "% of strokes" plot.y_range = Range1d(0,1.05*max(hist_norm)) hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ ('Power(W)','@left{int}'), ('% of strokes','@hist_norm'), ('Cumulative %','@histsum{int}'), ]) hover.mode = 'mouse' plot.extra_y_ranges = {"fraction": Range1d(start=0,end=105)} plot.line('right','histsum',source=source,color="red", y_range_name="fraction") plot.add_layout(LinearAxis(y_range_name="fraction", axis_label="Cumulative % of strokes"),'right') script, div = components(plot) return [script,div] def googlemap_chart(lat,lon,name=""): # plot tools TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair' map_options = GMapOptions(lat = lat.mean(),lng=lon.mean(), map_type="roadmap",zoom=11) plot = GMapPlot( x_range=DataRange1d(), y_range=DataRange1d(), map_options=map_options, api_key = "AIzaSyAgu1w9QSthaGPMLp8y9JedPoMc9sfEgJ8", plot_width=400,plot_height=400, toolbar_sticky=False, ) source = ColumnDataSource( data = dict( lat=lat, lon=lon, ) ) circle = Circle(x="lon",y="lat",size=5,fill_color="blue", fill_alpha=0.2,line_color=None) plot.add_glyph(source,circle) plot.add_tools(PanTool(), WheelZoomTool(), SaveTool(), ResizeTool(), ResetTool(), TapTool(),CrosshairTool(), ) plot.title.text = name plot.title.text_font="1.0em" script, div = components(plot) return [script,div] def interactive_cpchart(thedistances,thesecs,theavpower, theworkouts,promember=0): message = 0 # plot tools if (promember==1): TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' else: TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' x_axis_type = 'log' y_axis_type = 'linear' velo = thedistances/thesecs p = 500./velo p2 = get_datetimes(p) source = ColumnDataSource( data = dict( dist = thedistances, duration = thesecs, spm = 0*theavpower, tim = niceformat(get_datetimes(thesecs,tzinfo=1)), power = theavpower, pace = nicepaceformat(p2), ) ) # fitting the data to Paul if len(thedistances)>=2: paulslope, paulintercept,r,p,stderr = linregress(np.log10(thedistances),p) else: paulslope = 5.0/np.log10(2.0) paulintercept = p[0]-paulslope*np.log10(thedistances[0]) fitx = 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 = get_datetimes(fitp) sourcepaul = ColumnDataSource( data = dict( dist = 10**fitx, duration = fitt, power = fitpower, spm = 0*fitpower, tim = niceformat(get_datetimes(fitt,tzinfo=1)), pace = nicepaceformat(fitp2), ) ) # fitting the data to simple CP model # simpleslope, simpleintercept,r,p,stderr = linregress(1./thesecs,theavpower) # fitx = 1.e-4+np.arange(10000)/10000. # fitpower = simpleslope*fitx+simpleintercept # fitvelo = (fitpower/2.8)**(1./3.) # fitt = 1./fitx # fitdist = fitt*fitvelo # fitp = 500./fitvelo # fitp2 = get_datetimes(fitp) # sourcesimple = ColumnDataSource( # data = dict( # dist = fitdist, # duration = fitt, # power = fitpower, # tim = niceformat(get_datetimes(fitt)), # pace = nicepaceformat(fitp2), # ) # ) # fitting the data to three parameter CP model fitfunc = lambda pars,x: pars[0]/(1+(x/pars[2])) + pars[1]/(1+(x/pars[3])) errfunc = lambda pars,x,y: fitfunc(pars,x)-y p0 = [500,350,10,8000] p1 = p0 if len(thesecs)>=4: p1, success = optimize.leastsq(errfunc, p0[:], args = (thesecs,theavpower)) else: factor = fitfunc(p0,thesecs.mean())/theavpower.mean() p1 = [p0[0]/factor,p0[1]/factor,p0[2],p0[3]] fitt = 10**(4*np.arange(100)/100.) fitpower = fitfunc(p1,fitt) message = "" if len(fitpower[fitpower<0]) > 0: message = "CP model fit didn't give correct results" fitvelo = (fitpower/2.8)**(1./3.) fitdist = fitt*fitvelo fitp = 500./fitvelo fitp2 = get_datetimes(fitp) sourcecomplex = ColumnDataSource( data = dict( dist = fitdist, duration = fitt, tim = niceformat(get_datetimes(fitt,tzinfo=1)), spm = 0*fitpower, power = fitpower, pace = nicepaceformat(fitp2), ) ) # making the plot plot = Figure(tools=TOOLS,x_axis_type=x_axis_type, plot_width=900, toolbar_location="above", toolbar_sticky=False) plot.circle('duration','power',source=source,fill_color='red',size=15, legend='Power') plot.xaxis.axis_label = "Duration (seconds)" plot.yaxis.axis_label = "Power (W)" therows = [] for workout in theworkouts: f1 = workout.csvfilename rowdata = rdata(f1) if rowdata != 0: therows.append(rowdata) cpdata = cumcpdata(therows) velo = cpdata['Distance']/cpdata['Delta'] p = 500./velo p2 = get_datetimes(p) source2 = ColumnDataSource( data = dict( duration = cpdata['Delta'], power = cpdata['CP'], tim = niceformat(get_datetimes(cpdata['Delta'],tzinfo=1)), dist = cpdata['Distance'], pace = nicepaceformat(p2), ) ) plot.circle('duration','power',source=source2, fill_color='blue',size=3, legend = 'Power from segments') # for workout in theworkouts: # f1 = workout.csvfilename # rowdata = rdata(f1) # cpdata = rowdata.getcp() # source2 = ColumnDataSource( # data = dict( # duration = cpdata['Delta'], # power = cpdata['CP'], # dist = cpdata['Distance'], # ) # ) # plot.circle('duration','power',source=source2,fill_color='blue',size=3) hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ ('Duration ','@tim'), ('Power (W)','@power{int}'), ('Distance (m)','@dist{int}'), ('Pace (/500m)','@pace'), ]) 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.extra_y_ranges = {"distance": Range1d(start=0, # end=1.1*max(thedistances))} # plot.circle('duration','dist',source=source,fill_color='white',size=15, # legend='Distance', # y_range_name="distance") # plot.line('duration','dist',source=sourcepaul,y_range_name="distance") # plot.line('duration','dist',source=sourcesimple,legend="Simple CP model", # color='red',y_range_name="distance") # plot.line('duration','dist',source=sourcecomplex,legend="Simple CP model", # color='green',y_range_name="distance") # plot.add_layout(LinearAxis(y_range_name="distance", # axis_label="Distance (m)"),'right') plot.line('duration','power',source=sourcepaul,legend="Paul's Law") # plot.line('duration','power',source=sourcesimple,legend="Simple CP model", # color='red') plot.line('duration','power',source=sourcecomplex,legend="CP Model", color='green') script, div = components(plot) return [script,div,paulslope,paulintercept,p1,message] 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(plot_width=400,plot_height=300) # get user # u = User.objects.get(id=row.user.id) r = row.user u = r.user rr = rrower(hrmax=r.max,hrut2=r.ut2, hrut1=r.ut1,hrat=r.at, hrtr=r.tr,hran=r.an) rowdata = rdata(f1,rower=rr) if rowdata == 0: return 0 dist = rowdata.df.ix[:,'cum_dist'] try: vwind = rowdata.df.ix[:,'vwind'] winddirection = rowdata.df.ix[:,'winddirection'] bearing = rowdata.df.ix[:,'bearing'] except KeyError: rowdata.add_wind(0,0) rowdata.add_bearing() vwind = rowdata.df.ix[:,'vwind'] winddirection = rowdata.df.ix[:,'winddirection'] bearing = rowdata.df.ix[:,'winddirection'] rowdata.write_csv(f1) 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,resize,crosshair' else: TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair' # making the plot plot = Figure(tools=TOOLS,plot_width=400,height=500, # toolbar_location="below", toolbar_sticky=False, ) plot.line('dist','vwind',source=source,legend="Wind Speed (m/s)") plot.line('dist','tw',source=source,legend="Tail (+)/Head (-) Wind (m/s)",color='black') plot.title.text = row.name # plot.title.text_font_size=value("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.extra_y_ranges = {"winddirection": Range1d(start=0,end=360)} plot.line('dist','winddirection',source=source, legend='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(plot_width=400, ) # get user # u = User.objects.get(id=row.user.id) r = row.user u = r.user rr = rrower(hrmax=r.max,hrut2=r.ut2, hrut1=r.ut1,hrat=r.at, hrtr=r.tr,hran=r.an) rowdata = rdata(f1,rower=rr) if rowdata == 0: return "","CSV Data File Not Found" dist = rowdata.df.ix[:,'cum_dist'] try: vstream = rowdata.df.ix[:,'vstream'] except KeyError: rowdata.add_stream(0) vstream = rowdata.df.ix[:,'vstream'] rowdata.write_csv(f1) # plot tools if (promember==1): TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair' else: TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair' # making the plot plot = Figure(tools=TOOLS,plot_width=400,height=500, # toolbar_location="below", toolbar_sticky=False, ) plot.line(dist,vstream,legend="River Stream Velocity (m/s)") plot.title.text = row.name plot.title.text_font_size=value("1.0em") plot.xaxis.axis_label = "Distance (m)" plot.yaxis.axis_label = "River Current (m/s)" plot.y_range = Range1d(-2,2) script, div = components(plot) return [script,div] def interactive_chart(id=0,promember=0): # 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' else: TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' # 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 # get user # u = User.objects.get(id=row.user.id) r = row.user u = r.user rr = rrower(hrmax=r.max,hrut2=r.ut2, hrut1=r.ut1,hrat=r.at, hrtr=r.tr,hran=r.an) rowdata = rdata(f1,rower=rr) 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. p = rowdata.df.ix[:,' Stroke500mPace (sec/500m)'] hr = rowdata.df.ix[:,' HRCur (bpm)'] spm = rowdata.df.ix[:,' Cadence (stokes/min)'] cumdist = rowdata.df.ix[:,'cum_dist'] 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) t2 = get_datetimes(t,tzinfo=1) # p[p>3000] = 3000. p2 = get_datetimes(p) source = ColumnDataSource( data = dict( x=t2, y=hr, y2=p2, tf = niceformat(t2), pace = nicepaceformat(p2), heartrate = hr, spm=spm, spmc=np.rint(10*spm)/10., cumdist=cumdist, ) ) plot = Figure(x_axis_type="datetime",y_axis_type="datetime", plot_width=400, plot_height=400, toolbar_sticky=False, # toolbar_location="below", tools=TOOLS) # plot.line(t2,p2,legend="Pace") plot.line('x','y2',source=source,legend="Pace") plot.title.text = row.name plot.title.text_font_size=value("1.0em") plot.xaxis.axis_label = "Time" plot.yaxis.axis_label = "Pace (/500m)" plot.xaxis[0].formatter = DatetimeTickFormatter( hours = ["%H"], minutes = ["%M"], seconds = ["%S"], days = ["0"], months = [""], years = [""] ) plot.yaxis[0].formatter = DatetimeTickFormatter( seconds = ["%S"], minutes = ["%M"] ) ymax = datetime.datetime(2016,5,1,0,1,30) ymin = datetime.datetime(2016,5,1,0,2,30) if row.workouttype == 'water': ymax = datetime.datetime(2016,5,1,0,1,30) ymin = datetime.datetime(2016,5,1,0,3,30) plot.y_range = Range1d(ymin,ymax) hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ ('Time','@tf'), ('Pace','@pace'), ('HR','@heartrate'), ('SPM','@spmc{1.1}'), ('Distance','@cumdist{1.1}'), ]) hover.mode = 'mouse' plot.extra_y_ranges = {"hr": Range1d(start=100,end=200)} # plot.line(t2,hr,color="red",y_range_name="hr",legend="Heart Rate") plot.line('x','y',source=source,color="red", y_range_name="hr", legend="Heart Rate") plot.add_layout(LinearAxis(y_range_name="hr",axis_label="HR"),'right') plot.legend.location = "bottom_right" script, div = components(plot) return [script,div] def interactive_cum_flex_chart(theworkouts,promember=0, xparam='spm', yparam1='power', yparam2='hr', ): therows = [] for workout in theworkouts: f1 = workout.csvfilename rowdata = rdata(f1) if rowdata != 0: therows.append(rowdata.df) thedata = pd.concat(therows) 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', 'distance': 'Distance (m)', 'hr': 'Heart Rate (bpm)', 'spm': 'Stroke Rate (spm)', 'pace': 'Pace (/500m)', 'power': 'Power (Watt)', 'averageforce': 'Average Drive Force (lbs)', 'drivelength': 'Drive Length (m)', 'peakforce': 'Peak Drive Force (lbs)', 'driveenergy': 'Work per Stroke (J)', 'drivespeed': 'Drive Speed (m/s)', 'None': '', } yparamname1 = axlabels[yparam1] yparamname2 = axlabels[yparam2] yaxminima = { 'hr':100, 'spm':15, 'pace': datetime.datetime(2016,5,1,0,3,30), 'power': 0, 'averageforce': 0, 'peakforce': 0, 'drivelength':0.5, 'driveenergy': 0, 'drivespeed': 0, } yaxmaxima = { 'hr':200, 'spm':45, 'pace':datetime.datetime(2016,5,1,0,1,30), 'power': 600, 'averageforce':200, 'peakforce':400, 'drivelength':2.0, 'driveenergy': 1000, 'drivespeed':4, } thedata['driveenergy'] = thedata[' DriveLength (meters)']*thedata[' AverageDriveForce (lbs)']*4.44822 # throw out zeros from dataframe thedata = thedata[thedata[csvcolumns[yparam1]] > 0] thedata = thedata[thedata[csvcolumns[xparam]] > 0] if yparam2 != 'None': thedata = thedata[thedata[csvcolumns[yparam2]] > 0] # check if dataframe not empty if thedata.empty: return ['','

No non-zero data in selection

','',''] spm = thedata.ix[:,csvcolumns['spm']] f = thedata['TimeStamp (sec)'].diff().mean() if not np.isnan(f): windowsize = 2*(int(10./(f)))+1 else: windowsize = 5 if windowsize <= 3: windowsize = 5 if windowsize > 3: spm = savgol_filter(spm,windowsize,3) thedata[' Cadence (stokes/min)'] = spm drivelength = thedata[' DriveLength (meters)'] if windowsize > 3: drivelength = savgol_filter(drivelength,windowsize,3) thedata[' DriveLength (meters)'] = drivelength thedata['drivespeed'] = drivelength/thedata[' DriveTime (ms)']*1.0e3 x1 = thedata.ix[:,csvcolumns[xparam]] y1 = thedata.ix[:,csvcolumns[yparam1]] if yparam2 != 'None': y2 = thedata.ix[:,csvcolumns[yparam2]] else: y2 = y1 if xparam=='time': xaxmax = x1.max() xaxmin = x1.min() xaxmax = get_datetimes([xaxmax],tzinfo=1)[0] xaxmin = get_datetimes([xaxmin],tzinfo=1)[0] x1 = get_datetimes(x1,tzinfo=1) elif xparam=='distance': xaxmax = x1.max() xaxmin = x1.min() else: xaxmax = yaxmaxima[xparam] xaxmin = yaxminima[xparam] # average values if xparam != 'time': x1mean = x1.mean() else: x1mean = 0 y1mean = y1.mean() y2mean = y2.mean() if xparam != 'time': xvals = xaxmin+np.arange(100)*(xaxmax-xaxmin)/100. else: xvals = np.arange(100) x_axis_type = 'linear' y_axis_type = 'linear' if xparam == 'time': x_axis_type = 'datetime' if yparam1 == 'pace': y_axis_type = 'datetime' y1 = get_datetimes(y1) ymax = datetime.datetime(2016,5,1,0,1,30) ymin = datetime.datetime(2016,5,1,0,2,30) time = thedata.ix[:,csvcolumns['time']] hr = thedata.ix[:,csvcolumns['hr']] if windowsize > 3: hr = savgol_filter(hr,windowsize,3) pace = thedata.ix[:,csvcolumns['pace']] distance = thedata.ix[:,csvcolumns['distance']] power = thedata.ix[:,csvcolumns['power']] # 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' else: TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type, tools=TOOLS, toolbar_location="above", toolbar_sticky=False) x1means = Span(location=x1mean,dimension='height',line_color='green', line_dash=[6,6], line_width=2) y1means = Span(location=y1mean,dimension='width',line_color='blue', line_dash=[6,6],line_width=2) y2means = y1means if (xparam != 'time') and (xparam != 'distance'): plot.add_layout(x1means) plot.add_layout(y1means) source = ColumnDataSource( data = dict( x1=x1, y1=y1, y2=y2, time=niceformat(get_datetimes(time,tzinfo=1)), pace=nicepaceformat(get_datetimes(pace)), hr = hr, spm = spm, spmc=np.rint(10*spm)/10., distance=distance, power=power, ) ) source2 = ColumnDataSource( data = dict( x1=x1, y1=y1, y2=y2, time=niceformat(get_datetimes(time,tzinfo=1)), pace=nicepaceformat(get_datetimes(pace)), hr = hr, spm = spm, spmc=np.rint(10*spm)/10., distance=distance, power=power, ) ) # plot.circle('x1','y1',source=source,legend=yparam1,size=3) plot.circle('x1','y1',source=source2,fill_alpha=0.3,line_color=None, legend=yparamname1, ) plot.xaxis.axis_label = axlabels[xparam] plot.yaxis.axis_label = axlabels[yparam1] yrange1 = Range1d(start=yaxminima[yparam1],end=yaxmaxima[yparam1]) plot.y_range = yrange1 if (xparam != 'time') and (xparam != 'distance'): xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam]) plot.x_range = xrange1 if xparam == 'time': xrange1 = Range1d(start=xaxmin,end=xaxmax) plot.x_range = xrange1 plot.xaxis[0].formatter = DatetimeTickFormatter( hours = ["%H"], minutes = ["%M"], seconds = ["%S"], days = ["0"], months = [""], years = [""] ) if yparam1 == 'pace': plot.y_range = Range1d(ymin,ymax) plot.yaxis[0].formatter = DatetimeTickFormatter( seconds = ["%S"], minutes = ["%M"] ) if yparam2 != 'None': yrange2 = Range1d(start=yaxminima[yparam2],end=yaxmaxima[yparam2]) plot.extra_y_ranges = {"yax2": yrange2} plot.circle('x1','y2',color="red",y_range_name="yax2", legend=yparamname2, source=source2,fill_alpha=0.3,line_color=None) plot.add_layout(LinearAxis(y_range_name="yax2", axis_label=axlabels[yparam2]),'right') y2means = Span(location=y2mean,dimension='width',line_color='red', line_dash=[6,6],line_width=2,y_range_name="yax2") plot.add_layout(y2means) hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ ('Time','@time'), ('Pace','@pace'), ('HR','@hr'), ('SPM','@spmc{1.1}'), ('Power','@power{int}'), ]) hover.mode = 'mouse' callback = CustomJS(args = dict(source=source,source2=source2, x1means=x1means, y1means=y1means, y2means=y2means), code=""" var data = source.data var data2 = source2.data var x1 = data['x1'] var y1 = data['y1'] var y2 = data['y2'] var spm1 = data['spm'] var time1 = data['time'] var pace1 = data['pace'] var hr1 = data['hr'] var spmc1 = data['spmc'] var distance1 = data['distance'] var power1 = data['power'] var minspm = minspm.value var maxspm = maxspm.value var mindist = mindist.value var maxdist = maxdist.value var xm = 0 var ym1 = 0 var ym2 = 0 data2['x1'] = [] data2['y1'] = [] data2['y2'] = [] data2['spm'] = [] data2['time'] = [] data2['pace'] = [] data2['hr'] = [] data2['spmc'] = [] data2['distance'] = [] data2['power'] = [] data2['x1mean'] = [] data2['y1mean'] = [] data2['y2mean'] = [] data2['xvals'] = [] data2['y1vals'] = [] data2['y2vals'] = [] for (i=0; i=minspm && spm1[i]<=maxspm) { if (distance1[i]>=mindist && distance1[i]<=maxdist) { data2['x1'].push(x1[i]) data2['y1'].push(y1[i]) data2['y2'].push(y2[i]) data2['spm'].push(spm1[i]) data2['time'].push(time1[i]) data2['pace'].push(pace1[i]) data2['hr'].push(hr1[i]) data2['spmc'].push(spmc1[i]) data2['distance'].push(distance1[i]) data2['power'].push(power1[i]) xm += x1[i] ym1 += y1[i] ym2 += y2[i] } } } xm /= data2['x1'].length ym1 /= data2['x1'].length ym2 /= data2['x1'].length data2['x1mean'] = [xm,xm] data2['y1mean'] = [ym1,ym1] data2['y2mean'] = [ym2,ym2] x1means.location = xm y1means.location = ym1 y2means.location = ym2 source2.trigger('change'); """) slider_spm_min = Slider(start=15.0, end=55,value=15.0, step=.1, title="Min SPM",callback=callback) callback.args["minspm"] = slider_spm_min slider_spm_max = Slider(start=15.0, end=55,value=55.0, step=.1, title="Max SPM",callback=callback) callback.args["maxspm"] = slider_spm_max distmax = 100+100*int(distance.max()/100.) slider_dist_min = Slider(start=0,end=distmax,value=0,step=1, title="Min Distance",callback=callback) callback.args["mindist"] = slider_dist_min slider_dist_max = Slider(start=0,end=distmax,value=distmax, step=1, title="Max Distance",callback=callback) callback.args["maxdist"] = slider_dist_max layout = layoutrow([layoutcolumn([slider_spm_min, slider_spm_max, slider_dist_min, slider_dist_max, ], ), plot]) script, div = components(layout) js_resources = INLINE.render_js() css_resources = INLINE.render_css() return [script,div,js_resources,css_resources] def interactive_flex_chart(id=0,promember=0, xparam='time', yparam1='pace', yparam2='hr', plottype='line', workstrokesonly=False): 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', 'distance': 'Distance (m)', 'hr': 'Heart Rate (bpm)', 'spm': 'Stroke Rate (spm)', 'pace': 'Pace (/500m)', 'power': 'Power (Watt)', 'averageforce': 'Average Drive Force (lbs)', 'drivelength': 'Drive Length (m)', 'peakforce': 'Peak Drive Force (lbs)', 'driveenergy': 'Work per Stroke (J)', 'drivespeed': 'Drive Speed (m/s)', 'None': '', } yaxminima = { 'hr':100, 'spm':15, 'pace': datetime.datetime(2016,5,1,0,3,30), 'power': 0, 'averageforce': 0, 'peakforce': 0, 'drivelength':0.5, 'driveenergy': 0, 'drivespeed': 0, } yaxmaxima = { 'hr':200, 'spm':45, 'pace':datetime.datetime(2016,5,1,0,1,30), 'power': 600, 'averageforce':200, 'peakforce':400, 'drivelength':2.0, 'driveenergy': 1000, 'drivespeed':4, } # 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 r = row.user u = r.user rr = rrower(hrmax=r.max,hrut2=r.ut2, hrut1=r.ut1,hrat=r.at, hrtr=r.tr,hran=r.an) rowdata = rdata(f1,rower=rr) if rowdata == 0: return "","CSV Data File Not Found" workoutstateswork = [1,4,5,8,9,6,7] workoutstatesrest = [3] workoutstatetransition = [0,2,10,11,12,13] if workstrokesonly: try: rowdata.df = rowdata.df[~rowdata.df[' WorkoutState'].isin(workoutstatesrest)] except KeyError: pass rowdata.df['driveenergy'] = rowdata.df[' DriveLength (meters)']*rowdata.df[' AverageDriveForce (lbs)']*4.44822 f = rowdata.df['TimeStamp (sec)'].diff().mean() windowsize = 2*(int(10./(f)))+1 if windowsize <= 3: windowsize = 5 spm = rowdata.df.ix[:,csvcolumns['spm']] hr = rowdata.df.ix[:,csvcolumns['hr']] if windowsize > 3: spm = savgol_filter(spm,windowsize,3) hr = savgol_filter(hr,windowsize,3) rowdata.df[' Cadence (stokes/min)'] = spm rowdata.df[' HRCur (bpm)'] = hr drivelength = rowdata.df[' DriveLength (meters)'] if windowsize > 3: drivelength = savgol_filter(drivelength,windowsize,3) rowdata.df[' DriveLength (meters)'] = drivelength rowdata.df['drivespeed'] = drivelength/rowdata.df[' DriveTime (ms)']*1.0e3 # get user # u = User.objects.get(id=row.user.id) x1 = rowdata.df.ix[:,csvcolumns[xparam]] y1 = rowdata.df.ix[:,csvcolumns[yparam1]] if yparam2 != 'None': y2 = rowdata.df.ix[:,csvcolumns[yparam2]] else: y2 = y1 if xparam=='time': xaxmax = x1.max() xaxmin = x1.min() xaxmax = get_datetimes([xaxmax],tzinfo=1)[0] xaxmin = get_datetimes([xaxmin],tzinfo=1)[0] x1 = get_datetimes(x1,tzinfo=1) if xparam=='distance': xaxmax = x1.max() xaxmin = x1.min() # average values y1mean = y1.median()+0.0*np.arange(100) y2mean = y2.median()+0.0*np.arange(100) if xparam != 'time': x1mean = x1.median()+0.0*np.arange(100) else: x1mean = 0+0.0*np.arange(100) if xparam != 'time' and xparam != 'distance' and yparam1 != 'pace': xvals = yaxminima[xparam]+np.arange(100)*(yaxmaxima[xparam]-yaxminima[xparam])/100. y1vals = yaxminima[yparam1]+np.arange(100)*(yaxmaxima[yparam1]-yaxminima[yparam1])/100. else: xvals = np.arange(100) y1vals = np.arange(100) # constant power plot if yparam1 == 'driveenergy': if xparam == 'spm': yconstantpower = y1.median()*x1.median()/xvals x_axis_type = 'linear' y_axis_type = 'linear' if xparam == 'time': x_axis_type = 'datetime' if yparam1 == 'pace': y_axis_type = 'datetime' y1 = get_datetimes(y1) ymax = datetime.datetime(2016,5,1,0,1,30) ymin = datetime.datetime(2016,5,1,0,2,30) if row.workouttype == 'water': ymax = datetime.datetime(2016,5,1,0,1,30) ymin = datetime.datetime(2016,5,1,0,3,30) time = rowdata.df.ix[:,csvcolumns['time']] time = time-time[time.index[0]] hr = rowdata.df.ix[:,csvcolumns['hr']] pace = rowdata.df.ix[:,csvcolumns['pace']] distance = rowdata.df.ix[:,csvcolumns['distance']] power = rowdata.df.ix[:,csvcolumns['power']] # 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' else: TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type, tools=TOOLS, toolbar_sticky=False, plot_width=900, ) source = ColumnDataSource( data = dict( x1=x1, y1=y1, y2=y2, time=niceformat(get_datetimes(time,tzinfo=1)), pace=nicepaceformat(get_datetimes(pace)), hr = hr, spm = spm, spmc=np.rint(10*spm)/10., distance=distance, power=power, xvals=xvals, y1mean=y1mean, x1mean=x1mean, y1vals=y1vals, ) ) # average values plot.line('xvals','y1mean',color="black",source=source) plot.line('x1mean','y1vals',color="black",source=source) if yparam1 == 'driveenergy': if xparam == 'spm': plot.line(xvals,yconstantpower,color="green",legend="Constant Power") if plottype=='line': plot.line('x1','y1',source=source,legend=axlabels[yparam1]) elif plottype=='scatter': # plot.circle('x1','y1',source=source,legend=yparam1,size=3) plot.scatter('x1','y1',source=source,legend=axlabels[yparam1],fill_alpha=0.4, line_color=None) plot.title.text = row.name plot.title.text_font_size=value("1.0em") plot.xaxis.axis_label = axlabels[xparam] plot.yaxis.axis_label = axlabels[yparam1] yrange1 = Range1d(start=yaxminima[yparam1],end=yaxmaxima[yparam1]) plot.y_range = yrange1 if (xparam != 'time') and (xparam != 'distance'): xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam]) plot.x_range = xrange1 if xparam == 'time': xrange1 = Range1d(start=xaxmin,end=xaxmax) plot.x_range = xrange1 plot.xaxis[0].formatter = DatetimeTickFormatter( hours = ["%H"], minutes = ["%M"], seconds = ["%S"], days = ["0"], months = [""], years = [""] ) if yparam1 == 'pace': plot.y_range = Range1d(ymin,ymax) plot.yaxis[0].formatter = DatetimeTickFormatter( seconds = ["%S"], minutes = ["%M"] ) if yparam2 != 'None': yrange2 = Range1d(start=yaxminima[yparam2],end=yaxmaxima[yparam2]) plot.extra_y_ranges = {"yax2": yrange2} plot.line(xvals,y2mean,color="black",y_range_name="yax2") if plottype=='line': plot.line('x1','y2',color="red",y_range_name="yax2", legend=axlabels[yparam2], source=source) elif plottype=='scatter': # plot.circle(x1,y2,color="red",y_range_name="yax2",legend=yparam2, # source=source,size=3) plot.scatter('x1','y2',source=source,legend=axlabels[yparam2] ,fill_alpha=0.4, line_color=None,color="red",y_range_name="yax2") plot.add_layout(LinearAxis(y_range_name="yax2", axis_label=axlabels[yparam2]),'right') hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ ('Time','@time'), ('Distance','@distance{int}'), ('Pace','@pace'), ('HR','@hr'), ('SPM','@spmc{1.1}'), ('Power','@power{int}'), ]) hover.mode = 'mouse' script, div = components(plot) return [script,div] def interactive_flex_chart2(id=0,promember=0, xparam='time', yparam1='pace', yparam2='hr', plottype='line', workstrokesonly=False): 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', 'distance': 'Distance (m)', 'hr': 'Heart Rate (bpm)', 'spm': 'Stroke Rate (spm)', 'pace': 'Pace (/500m)', 'power': 'Power (Watt)', 'averageforce': 'Average Drive Force (lbs)', 'drivelength': 'Drive Length (m)', 'peakforce': 'Peak Drive Force (lbs)', 'driveenergy': 'Work per Stroke (J)', 'drivespeed': 'Drive Speed (m/s)', 'None': '', } yaxminima = { 'hr':100, 'spm':15, 'pace': datetime.datetime(2016,5,1,0,3,30), 'power': 0, 'averageforce': 0, 'peakforce': 0, 'drivelength':0.5, 'driveenergy': 0, 'drivespeed': 0, } yaxmaxima = { 'hr':200, 'spm':45, 'pace':datetime.datetime(2016,5,1,0,1,30), 'power': 600, 'averageforce':200, 'peakforce':400, 'drivelength':2.0, 'driveenergy': 1000, 'drivespeed':4, } # 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 r = row.user u = r.user rr = rrower(hrmax=r.max,hrut2=r.ut2, hrut1=r.ut1,hrat=r.at, hrtr=r.tr,hran=r.an) rowdata = rdata(f1,rower=rr) if rowdata == 0: return "","CSV Data File Not Found" workoutstateswork = [1,4,5,8,9,6,7] workoutstatesrest = [3] workoutstatetransition = [0,2,10,11,12,13] if workstrokesonly: try: rowdata.df = rowdata.df[~rowdata.df[' WorkoutState'].isin(workoutstatesrest)] except KeyError: pass rowdata.df['driveenergy'] = rowdata.df[' DriveLength (meters)']*rowdata.df[' AverageDriveForce (lbs)']*4.44822 spm = rowdata.df.ix[:,csvcolumns['spm']] hr = rowdata.df.ix[:,csvcolumns['hr']] 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) hr = savgol_filter(hr,windowsize,3) rowdata.df[' Cadence (stokes/min)'] = spm rowdata.df[' HRCur (bpm)'] = hr drivelength = rowdata.df[' DriveLength (meters)'] if windowsize > 3: drivelength = savgol_filter(drivelength,windowsize,3) rowdata.df[' DriveLength (meters)'] = drivelength rowdata.df['drivespeed'] = drivelength/rowdata.df[' DriveTime (ms)']*1.0e3 # get user # u = User.objects.get(id=row.user.id) x1 = rowdata.df.ix[:,csvcolumns[xparam]] y1 = rowdata.df.ix[:,csvcolumns[yparam1]] if yparam2 != 'None': y2 = rowdata.df.ix[:,csvcolumns[yparam2]] else: y2 = y1 if xparam=='time': xaxmax = x1.max() xaxmin = x1.min() xaxmax = get_datetimes([xaxmax],tzinfo=1)[0] xaxmin = get_datetimes([xaxmin],tzinfo=1)[0] x1 = get_datetimes(x1,tzinfo=1) elif xparam=='distance': xaxmax = x1.max() xaxmin = x1.min() else: xaxmax = yaxmaxima[xparam] xaxmin = yaxminima[xparam] # average values if xparam != 'time': x1mean = x1.mean() else: x1mean = 0 y1mean = y1.mean() y2mean = y2.mean() if xparam != 'time': xvals = xaxmin+np.arange(100)*(xaxmax-xaxmin)/100. else: xvals = np.arange(100) # constant power plot if yparam1 == 'driveenergy': if xparam == 'spm': yconstantpower = y1.median()*x1.median()/xvals x_axis_type = 'linear' y_axis_type = 'linear' if xparam == 'time': x_axis_type = 'datetime' if yparam1 == 'pace': y_axis_type = 'datetime' y1 = get_datetimes(y1) ymax = datetime.datetime(2016,5,1,0,1,30) ymin = datetime.datetime(2016,5,1,0,2,30) if row.workouttype == 'water': ymax = datetime.datetime(2016,5,1,0,1,30) ymin = datetime.datetime(2016,5,1,0,3,30) time = rowdata.df.ix[:,csvcolumns['time']] time = time-time[time.index[0]] hr = rowdata.df.ix[:,csvcolumns['hr']] pace = rowdata.df.ix[:,csvcolumns['pace']] distance = rowdata.df.ix[:,csvcolumns['distance']] power = rowdata.df.ix[:,csvcolumns['power']] # prepare data source = ColumnDataSource( data = dict( x1=x1, y1=y1, y2=y2, time=niceformat(get_datetimes(time,tzinfo=1)), pace=nicepaceformat(get_datetimes(pace)), hr = hr, spm = spm, spmc=np.rint(10*spm)/10., distance=distance, power=power, # xvals=xvals, y1mean=[y1mean,y1mean], y2mean=[y2mean,y2mean], x1mean=[x1mean,x1mean], ) ) # second source for filtering source2 = ColumnDataSource( data = dict( x1=x1, y1=y1, y2=y2, time=niceformat(get_datetimes(time,tzinfo=1)), pace=nicepaceformat(get_datetimes(pace)), hr = hr, spm = spm, spmc=np.rint(10*spm)/10., distance=distance, power=power, # xvals=xvals, y1mean=[y1mean,y1mean], y2mean=[y2mean,y2mean], x1mean=[x1mean,x1mean], ) ) # 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' else: TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' sizing_mode = 'fixed' # 'scale_width' also looks nice with this example plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type, tools=TOOLS, toolbar_sticky=False, # plot_width=900, ) x1means = Span(location=x1mean,dimension='height',line_color='green', line_dash=[6,6], line_width=2) y1means = Span(location=y1mean,dimension='width',line_color='blue', line_dash=[6,6],line_width=2) y2means = y1means if (xparam != 'time') and (xparam != 'distance'): plot.add_layout(x1means) plot.add_layout(y1means) # average values if yparam1 == 'driveenergy': if xparam == 'spm': plot.line(xvals,yconstantpower,color="green",legend="Constant Power") if plottype=='line': plot.line('x1','y1',source=source2,legend=axlabels[yparam1]) elif plottype=='scatter': # plot.circle('x1','y1',source=source2,legend=yparam1,size=3) plot.scatter('x1','y1',source=source2,legend=axlabels[yparam1],fill_alpha=0.4, line_color=None) plot.title.text = row.name plot.title.text_font_size=value("1.0em") plot.xaxis.axis_label = axlabels[xparam] plot.yaxis.axis_label = axlabels[yparam1] yrange1 = Range1d(start=yaxminima[yparam1],end=yaxmaxima[yparam1]) plot.y_range = yrange1 if (xparam != 'time') and (xparam != 'distance'): xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam]) plot.x_range = xrange1 if xparam == 'time': xrange1 = Range1d(start=xaxmin,end=xaxmax) plot.x_range = xrange1 plot.xaxis[0].formatter = DatetimeTickFormatter( hours = ["%H"], minutes = ["%M"], seconds = ["%S"], days = ["0"], months = [""], years = [""] ) if yparam1 == 'pace': plot.y_range = Range1d(ymin,ymax) plot.yaxis[0].formatter = DatetimeTickFormatter( seconds = ["%S"], minutes = ["%M"] ) if yparam2 != 'None': yrange2 = Range1d(start=yaxminima[yparam2],end=yaxmaxima[yparam2]) plot.extra_y_ranges = {"yax2": yrange2} if plottype=='line': plot.line('x1','y2',color="red",y_range_name="yax2", legend=axlabels[yparam2], source=source2) elif plottype=='scatter': # plot.circle(x1,y2,color="red",y_range_name="yax2",legend=yparam2, # source=source,size=3) plot.scatter('x1','y2',source=source2,legend=axlabels[yparam2] ,fill_alpha=0.4, line_color=None,color="red",y_range_name="yax2") plot.add_layout(LinearAxis(y_range_name="yax2", axis_label=axlabels[yparam2]),'right') y2means = Span(location=y2mean,dimension='width',line_color='red', line_dash=[6,6],line_width=2,y_range_name="yax2") plot.add_layout(y2means) hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ ('Time','@time'), ('Distance','@distance'), ('Pace','@pace'), ('HR','@hr'), ('SPM','@spmc{1.1}'), ('Power','@power{int}'), ]) hover.mode = 'mouse' callback = CustomJS(args = dict(source=source,source2=source2, x1means=x1means, y1means=y1means, y2means=y2means), code=""" var data = source.data var data2 = source2.data var x1 = data['x1'] var y1 = data['y1'] var y2 = data['y2'] var spm1 = data['spm'] var time1 = data['time'] var pace1 = data['pace'] var hr1 = data['hr'] var spmc1 = data['spmc'] var distance1 = data['distance'] var power1 = data['power'] var minspm = minspm.value var maxspm = maxspm.value var mindist = mindist.value var maxdist = maxdist.value var xm = 0 var ym1 = 0 var ym2 = 0 data2['x1'] = [] data2['y1'] = [] data2['y2'] = [] data2['spm'] = [] data2['time'] = [] data2['pace'] = [] data2['hr'] = [] data2['spmc'] = [] data2['distance'] = [] data2['power'] = [] data2['x1mean'] = [] data2['y1mean'] = [] data2['y2mean'] = [] data2['xvals'] = [] data2['y1vals'] = [] data2['y2vals'] = [] for (i=0; i=minspm && spm1[i]<=maxspm) { if (distance1[i]>=mindist && distance1[i]<=maxdist) { data2['x1'].push(x1[i]) data2['y1'].push(y1[i]) data2['y2'].push(y2[i]) data2['spm'].push(spm1[i]) data2['time'].push(time1[i]) data2['pace'].push(pace1[i]) data2['hr'].push(hr1[i]) data2['spmc'].push(spmc1[i]) data2['distance'].push(distance1[i]) data2['power'].push(power1[i]) xm += x1[i] ym1 += y1[i] ym2 += y2[i] } } } xm /= data2['x1'].length ym1 /= data2['x1'].length ym2 /= data2['x1'].length data2['x1mean'] = [xm,xm] data2['y1mean'] = [ym1,ym1] data2['y2mean'] = [ym2,ym2] x1means.location = xm y1means.location = ym1 y2means.location = ym2 source2.trigger('change'); """) slider_spm_min = Slider(start=15.0, end=55,value=15.0, step=.1, title="Min SPM",callback=callback) callback.args["minspm"] = slider_spm_min slider_spm_max = Slider(start=15.0, end=55,value=55.0, step=.1, title="Max SPM",callback=callback) callback.args["maxspm"] = slider_spm_max distmax = 100+100*int(distance.max()/100.) slider_dist_min = Slider(start=0,end=distmax,value=0,step=1, title="Min Distance",callback=callback) callback.args["mindist"] = slider_dist_min slider_dist_max = Slider(start=0,end=distmax,value=distmax, step=1, title="Max Distance",callback=callback) callback.args["maxdist"] = slider_dist_max layout = layoutrow([layoutcolumn([slider_spm_min, slider_spm_max, slider_dist_min, slider_dist_max, ], ), plot]) script, div = components(layout) js_resources = INLINE.render_js() css_resources = INLINE.render_css() return [script,div,js_resources,css_resources] def interactive_bar_chart(id=0,promember=0): # check if valid ID exists (workout exists) row = Workout.objects.get(id=id) f1 = row.csvfilename # create interactive plot plot = Figure(plot_width=400,plot_height=300) # get user # u = User.objects.get(id=row.user.id) r = row.user u = r.user rr = rrower(hrmax=r.max,hrut2=r.ut2, hrut1=r.ut1,hrat=r.at, hrtr=r.tr,hran=r.an) rowdata = rdata(f1,rower=rr) 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. 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 if (promember==1): TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' else: TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' t2 = get_datetimes(t,tzinfo=1) p2 = get_datetimes(p) source = ColumnDataSource( data = dict( x=t2, x_right = get_datetimes(t+time_increments,tzinfo=1), 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, ) ) 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") plot.xaxis.axis_label = "Time" plot.yaxis.axis_label = "Pace (/500m)" plot.xaxis[0].formatter = DatetimeTickFormatter( hours ="", minutes = ["%M"], seconds = ["%S"], days = ["0"], months = [""], years = [""] ) plot.yaxis[0].formatter = DatetimeTickFormatter( seconds = ["%S"], minutes = ["%M"], ) ymax = datetime.datetime(2016,5,1,0,1,30) ymin = datetime.datetime(2016,5,1,0,2,30) if row.workouttype == 'water': ymax = datetime.datetime(2016,5,1,0,1,30) ymin = datetime.datetime(2016,5,1,0,3,30) plot.y_range = Range1d(ymin,ymax) hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ ('Time','@tf'), ('Pace','@pace'), ('HR','@heartrate'), ('SPM','@spmc{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', 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 x1 = rowdata1.df.ix[:,csvcolumns[xparam]] x2 = rowdata2.df.ix[:,csvcolumns[xparam]] y1 = rowdata1.df.ix[:,csvcolumns[yparam]] y2 = rowdata2.df.ix[:,csvcolumns[yparam]] if xparam=='time': x1 = x1-x1[0] x2 = x2-x2[0] x1 = get_datetimes(x1,tzinfo=1) x2 = get_datetimes(x2,tzinfo=1) x_axis_type = 'linear' y_axis_type = 'linear' if xparam == 'time': x_axis_type = 'datetime' if yparam == 'pace': y_axis_type = 'datetime' y1 = get_datetimes(y1) y2 = get_datetimes(y2) ymax = datetime.datetime(2016,5,1,0,1,30) ymin = datetime.datetime(2016,5,1,0,2,30) if row1.workouttype == 'water': ymax = datetime.datetime(2016,5,1,0,1,30) ymin = datetime.datetime(2016,5,1,0,3,30) time1 = rowdata1.df.ix[:,csvcolumns['time']] time2 = rowdata2.df.ix[:,csvcolumns['time']] time1 = time1-time1[0] time2 = time2-time2[0] hr1 = rowdata1.df.ix[:,csvcolumns['hr']] hr2 = rowdata2.df.ix[:,csvcolumns['hr']] pace1 = rowdata1.df.ix[:,csvcolumns['pace']] pace2 = rowdata2.df.ix[:,csvcolumns['pace']] distance1 = rowdata1.df.ix[:,csvcolumns['distance']] distance2 = rowdata2.df.ix[:,csvcolumns['distance']] if (promember==1): TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' else: TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' source = ColumnDataSource( data = dict( x1=x1, x2=x2, y1=y1, y2=y2, time1=niceformat(get_datetimes(time1,tzinfo=1)), time2=niceformat(get_datetimes(time2,tzinfo=1)), pace1=nicepaceformat(get_datetimes(pace1)), pace2=nicepaceformat(get_datetimes(pace2)), hr1 = hr1, hr2 = hr2, spm1 = spm1, spm2 = spm2, spm1c=np.rint(10*spm1)/10., spm2c=np.rint(10*spm2)/10., distance1=distance1, distance2=distance2, ) ) # create interactive plot plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type, tools=TOOLS, plot_width=920, # toolbar_location="above", toolbar_sticky=False) # plot.multi_line([x1,x2],[y1,y2],color=["blue","red"]) if plottype=='line': plot.line('x1','y1',source=source,color="blue",legend=row1.name) plot.line('x2','y2',source=source,color="red",legend=row2.name) elif plottype=='scatter': # plot.circle('x1','y1',source=source,color="blue",legend=row1.name,size=3) # plot.circle('x2','y2',source=source,color="red",legend=row2.name,size=3) plot.scatter('x1','y1',source=source,legend=row1.name,fill_alpha=0.4, line_color=None) plot.scatter('x2','y2',source=source,legend=row2.name,fill_alpha=0.4, line_color=None,color="red") # plot.scatter('x1','y1',source=source,color="blue") # plot.scatter('x2','y2',source=source,color="red") 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] if xparam == 'time': plot.xaxis[0].formatter = DatetimeTickFormatter( hours = ["%H"], minutes = ["%M"], seconds = ["%S"], days = ["0"], months = [""], years = [""] ) if yparam == 'pace': plot.y_range = Range1d(ymin,ymax) plot.yaxis[0].formatter = DatetimeTickFormatter( seconds = ["%S"], minutes = ["%M"] ) #hover = [t for t in plot.tools if isinstance(t, HoverTool)][0] hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ ('time1','@time1'), ('time2','@time2'), ('pace1','@pace1'), ('pace2','@pace2'), ('hr1','@hr1'), ('hr2','@hr2'), ('spm1','@spm1c{1.1}'), ('spm2','@spm2c{1.1}'), ('distance1','@distance1{5}'), ('distance2','@distance2{5}'), ]) hover.mode = 'mouse' script, div = components(plot) return [script,div] def interactive_otw_advanced_pace_chart(id=0,promember=0): # check if valid ID exists (workout exists) row = Workout.objects.get(id=id) f1 = row.csvfilename # get user # u = User.objects.get(id=row.user.id) r = row.user u = r.user rowdata = rdata(f1) 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. 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 = get_datetimes(t,tzinfo=1) p2 = get_datetimes(p) nowindp2 = get_datetimes(nowindpace) ergpace2 = get_datetimes(ergpace) # 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' else: 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., ) ) plot = Figure(x_axis_type="datetime",y_axis_type="datetime", tools=TOOLS, plot_width=920, toolbar_sticky=False) plot.title.text = row.name plot.title.text_font_size=value("1.2em") plot.xaxis.axis_label = "Time" plot.yaxis.axis_label = "Pace (/500m)" plot.xaxis[0].formatter = DatetimeTickFormatter( hours = ["%H"], minutes = ["%M"], seconds = ["%S"], days = ["0"], months = [""], years = [""] ) plot.yaxis[0].formatter = DatetimeTickFormatter( seconds = ["%S"], minutes = ["%M"] ) ymax = datetime.datetime(2016,5,1,0,1,30) ymin = datetime.datetime(2016,5,1,0,3,30) plot.y_range = Range1d(ymin,ymax) 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") hover.tooltips = OrderedDict([ ('Time','@tf'), ('Pace','@pace'), ('Corrected Pace','@nowindpace'), ('Equiv. Erg Pace','@ergpace'), ('HR','@heartrate'), ('SPM','@spmc{1.1}'), ]) hover.mode = 'mouse' script, div = components(plot) return [script,div]