diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index f1f79cbe..d5abd874 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -267,9 +267,10 @@ def interactive_workouttype_piechart(workouts): for w in workouts: try: - label = mytypes.workouttypes_ordered[w.workouttype] + # label = mytypes.workouttypes_ordered[w.workouttype] + label = w.workouttype except KeyError: - labels = w.workouttype + label = w.workouttype try: datadict[label] += 60*(60*w.duration.hour+w.duration.minute)+w.duration.second except KeyError: @@ -277,13 +278,15 @@ def interactive_workouttype_piechart(workouts): data = pd.Series(datadict).reset_index(name='value').rename(columns={'index':'type'}) data['angle'] = data['value']/data['value'].sum() * 2*pi - if len(datadict)>2: - data['color'] = Category10[len(datadict)] - elif len(datadict)==2: - data['color'] = ['orange','lightblue'] - else: - data['color'] = ['lightblue'] - data['totaltime'] = pd.Series([pretty_timedelta(v) for v in data['value']]) + + + + + data = pd.DataFrame(data) + data['color'] = data['type'].apply(lambda x:mytypes.color_map[x]) + data['totaltime'] = data['value'].apply(lambda x:pretty_timedelta(x)) + data['type'] = data['type'].apply(lambda x:mytypes.workouttypes_ordered[x]) + p = figure(plot_height=350, title="Types", toolbar_location=None, tools="hover,save", tooltips="@type: @totaltime", x_range=(-0.5, 1.0)) @@ -410,6 +413,7 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type',toolbar_lo durations = [] links = [] + rowersinitials = {} seen = ['seen'] idseen = [] @@ -456,6 +460,7 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type',toolbar_lo ) ) + types.append(w.workouttype) try: rowers.append(rowersinitials[w.user.id]) @@ -486,6 +491,7 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type',toolbar_lo durations.append(0) links.append('') types.append('rower') + try: rowers.append(rowers[0]) except IndexError: @@ -506,24 +512,24 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type',toolbar_lo 'link':links, } - types_ind = list(set(types)) - + dim_expr = hv.dim('type').categorize(mytypes.color_map) df = pd.DataFrame(thedict) source = ColumnDataSource(df) df.sort_values('date_sorting',inplace=True) + #clrs = hv.Cycle(df['colors'].values) hv.extension('bokeh') if stack == 'type': table = hv.Table(df,[('date','Date'),('type','Workout Type')],[('duration','Minutes'),('link','link')]) + else: table = hv.Table(df,[('date','Date'),('rower','Rower')],[('duration','Minutes'),('link','link')]) - bars=table.to.bars(['date',stack],['duration']) bars.opts( opts.Bars(color=hv.Cycle('Category10'), show_legend=True, stacked=True, @@ -548,6 +554,168 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type',toolbar_lo + callback = CustomJS(args={'links':df.link}, code=""" + var index = cb_data.source.selected['1d'].indices[0]; + console.log(links); + console.log(index); + console.log(links[index]); + window.location.href = links[index] + """) + + taptool.callback = callback + + + script,div = components(p) + return script,div + +def interactive_activitychart2(workouts,startdate,enddate,stack='type',toolbar_location=None): + + dates = [] + dates_sorting = [] + types = [] + rowers = [] + durations = [] + links = [] + + + rowersinitials = {} + seen = ['seen'] + idseen = [] + + startdate = datetime.datetime(year=startdate.year,month=startdate.month,day=startdate.day) + enddate = datetime.datetime(year=enddate.year,month=enddate.month,day=enddate.day) + + duration = enddate-startdate + + totaldays = duration.total_seconds()/(24*3600) + + + for w in workouts: + aantal=1 + initials = w.user.user.first_name[0:aantal]+w.user.user.last_name[0:aantal] + if w.user.id not in idseen: + while initials in seen: + aantal += 1 + initials = w.user.user.first_name[0:aantal]+w.user.user.last_name[0:aantal] + + seen.append(initials) + idseen.append(w.user.id) + rowersinitials[w.user.id] = initials + + + + for w in workouts: + dd = w.date.strftime('%m/%d') + dd2 = w.date.strftime('%Y/%m/%d') + dd3 = w.date.strftime('%Y/%m') + du = w.duration.hour*60+w.duration.minute + + if totaldays<30: + dates.append(dd) + dates_sorting.append(dd2) + else: + dates.append(dd3) + dates_sorting.append(dd3) + durations.append(du) + links.append( + "{siteurl}/rowers/workout/{code}/".format( + siteurl = settings.SITE_URL, + code = encoder.encode_hex(w.id) + ) + ) + + + types.append(w.workouttype) + try: + rowers.append(rowersinitials[w.user.id]) + except IndexError: + rowers.append(str(w.user)) + + try: + d = utc.localize(startdate) + except (ValueError,AttributeError): + d = startdate + + try: + enddate = utc.localize(enddate) + except (ValueError,AttributeError): + pass + + # add dates with no activity + while d<=enddate: + dd = d.strftime('%d') + + + if totaldays<30: + dates.append(d.strftime('%m/%d')) + dates_sorting.append(d.strftime('%Y/%m/%d')) + else: + dates.append(d.strftime('%Y/%m')) + dates_sorting.append(d.strftime('%Y/%m')) + durations.append(0) + links.append('') + types.append('rower') + + try: + rowers.append(rowers[0]) + except IndexError: + try: + rowers.append(str(workouts[0].user)) + except IndexError: + rowers.append(' ') + + d += datetime.timedelta(days=1) + + + thedict = { + 'date':dates, + 'date_sorting':dates_sorting, + 'duration':durations, + 'type':types, + 'rower':rowers, + 'link':links, + } + + dim_expr = hv.dim('type').categorize(mytypes.color_map) + + df = pd.DataFrame(thedict) + + + source = ColumnDataSource(df) + + df.sort_values('date_sorting',inplace=True) + #clrs = hv.Cycle(df['colors'].values) + + hv.extension('bokeh') + + + table = hv.Table(df,[('date','Date'),('type','Workout Type')],[('duration','Minutes'),('link','link')]) + + + bars=table.to.bars(['date',stack],['duration']) + bars.opts( + opts.Bars(color=dim_expr, show_legend=True, stacked=True, + tools=['tap','hover'], width=550, xrotation=45,padding=(0,(0,.1)), + legend_position='bottom',show_frame=True)) + + + + p = hv.render(bars) + + p.title.text = 'Activity {d1} to {d2}'.format( + d1 = startdate.strftime("%Y-%m-%d"), + d2 = enddate.strftime("%Y-%m-%d"), + ) + + p.plot_width=550 + p.plot_height=350 + p.toolbar_location = toolbar_location + p.sizing_mode = 'scale_width' + url = "http://rowsandall.com/rowers/workout/@duration/" + taptool = p.select(type=TapTool) + + + callback = CustomJS(args={'links':df.link}, code=""" var index = cb_data.source.selected['1d'].indices[0]; console.log(links); diff --git a/rowers/mytypes.py b/rowers/mytypes.py index e8b7aa9b..817884f4 100644 --- a/rowers/mytypes.py +++ b/rowers/mytypes.py @@ -270,6 +270,12 @@ rowtypes = ( checktypes = [i[0] for i in workouttypes] +from bokeh.palettes import Category10 + + +colors = Category10[9]+Category10[9]+Category10[9]+Category10[9] +color_map = {checktypes[i]:colors[i] for i in range(len(checktypes))} + workoutsources = ( ('strava','strava'), ('concept2','concept2'), diff --git a/rowers/templates/history.html b/rowers/templates/history.html index 16e6984c..0e3af386 100644 --- a/rowers/templates/history.html +++ b/rowers/templates/history.html @@ -30,7 +30,7 @@