different pie chart for types
This commit is contained in:
@@ -26,6 +26,7 @@ from bokeh.models import CustomJS,Slider, TextInput,BoxAnnotation
|
|||||||
from bokeh.resources import CDN,INLINE
|
from bokeh.resources import CDN,INLINE
|
||||||
from bokeh.embed import components
|
from bokeh.embed import components
|
||||||
from bokeh.layouts import layout,widgetbox
|
from bokeh.layouts import layout,widgetbox
|
||||||
|
from bokeh.palettes import Category20c
|
||||||
from bokeh.layouts import row as layoutrow
|
from bokeh.layouts import row as layoutrow
|
||||||
from bokeh.layouts import column as layoutcolumn
|
from bokeh.layouts import column as layoutcolumn
|
||||||
from bokeh.models import LinearAxis,LogAxis,Range1d,DatetimeTickFormatter,HoverTool
|
from bokeh.models import LinearAxis,LogAxis,Range1d,DatetimeTickFormatter,HoverTool
|
||||||
@@ -37,6 +38,7 @@ from bokeh.models import (
|
|||||||
ResetTool, TapTool,CrosshairTool,BoxZoomTool,
|
ResetTool, TapTool,CrosshairTool,BoxZoomTool,
|
||||||
Span, Label
|
Span, Label
|
||||||
)
|
)
|
||||||
|
from bokeh.transform import cumsum
|
||||||
from bokeh.models.glyphs import ImageURL
|
from bokeh.models.glyphs import ImageURL
|
||||||
from bokeh.models import OpenURL, TapTool
|
from bokeh.models import OpenURL, TapTool
|
||||||
from rowers.opaque import encoder
|
from rowers.opaque import encoder
|
||||||
@@ -251,65 +253,48 @@ def interactive_hr_piechart(df,rower,title):
|
|||||||
|
|
||||||
return components(z)
|
return components(z)
|
||||||
|
|
||||||
|
def pretty_timedelta(secs):
|
||||||
|
hours, remainder = divmod(secs,3600)
|
||||||
|
minutes, seconds = divmod(remainder,60)
|
||||||
|
|
||||||
|
return '{}:{:02}:{:02}'.format(int(hours),int(minutes),int(seconds))
|
||||||
|
|
||||||
def interactive_workouttype_piechart(workouts):
|
def interactive_workouttype_piechart(workouts):
|
||||||
if len(workouts) == 0:
|
if len(workouts) == 0:
|
||||||
return "","Not enough workouts to make a chart"
|
return "","Not enough workouts to make a chart"
|
||||||
|
|
||||||
datadict = {}
|
datadict = {}
|
||||||
labels = []
|
|
||||||
types = []
|
|
||||||
|
|
||||||
for w in workouts:
|
for w in workouts:
|
||||||
try:
|
try:
|
||||||
datadict[w.workouttype] += 3600*w.duration.hour+60*w.duration.minute+w.duration.second
|
label = mytypes.workouttypes_ordered[w.workouttype]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
datadict[w.workouttype] = 3600*w.duration.hour+60*w.duration.minute+w.duration.second
|
labels = w.workouttype
|
||||||
types += [w.workouttype]
|
|
||||||
try:
|
try:
|
||||||
labels += [mytypes.workouttypes_ordered[w.workouttype]]
|
datadict[label] += 60*(60*w.duration.hour+w.duration.minute)+w.duration.second
|
||||||
except KeyError:
|
except KeyError:
|
||||||
labels += [w.workouttype]
|
datadict[label] = 60*(60*w.duration.hour+w.duration.minute)+w.duration.second
|
||||||
|
|
||||||
total = 0
|
data = pd.Series(datadict).reset_index(name='value').rename(columns={'index':'type'})
|
||||||
source_starts = [0]
|
data['angle'] = data['value']/data['value'].sum() * 2*pi
|
||||||
source_ends = []
|
data['color'] = Category20c[len(datadict)]
|
||||||
for type in types:
|
data['totaltime'] = pd.Series([pretty_timedelta(v) for v in data['value']])
|
||||||
total += datadict[type]
|
|
||||||
source_starts.append(total)
|
|
||||||
source_ends.append(total)
|
|
||||||
|
|
||||||
source_ends.append(total)
|
p = figure(plot_height=350, title="Types", toolbar_location=None,
|
||||||
|
tools="hover,save", tooltips="@type: @totaltime", x_range=(-0.5, 1.0))
|
||||||
|
|
||||||
source_starts = pd.Series(source_starts)*2*pi/total
|
p.wedge(x=0, y=1, radius=0.4,
|
||||||
source_ends = pd.Series(source_ends)*2*pi/total
|
start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'),
|
||||||
|
line_color="white", fill_color='color', source=data,legend='type', )
|
||||||
|
|
||||||
size = 350
|
p.axis.axis_label=None
|
||||||
TOOLS = 'save'
|
p.axis.visible=False
|
||||||
|
p.grid.grid_line_color = None
|
||||||
|
p.outline_line_color = None
|
||||||
|
p.toolbar_location = 'right'
|
||||||
|
|
||||||
z = figure(title="Workout Types", x_range=(-1,1), y_range=(-1,1), width=size, height=size,
|
return components(p)
|
||||||
tools=TOOLS,
|
|
||||||
)
|
|
||||||
|
|
||||||
colors = palette
|
|
||||||
|
|
||||||
print(source_ends)
|
|
||||||
print(labels)
|
|
||||||
|
|
||||||
for start, end , legend, color in zip(source_starts, source_ends, labels,
|
|
||||||
colors[0:len(source_starts)]):
|
|
||||||
print(start,end,color,legend)
|
|
||||||
z.wedge(x=0, y=0, radius=1, start_angle=start, end_angle=end, color=color, legend=legend)
|
|
||||||
|
|
||||||
|
|
||||||
z.toolbar_location = 'right'
|
|
||||||
z.legend.location = 'top_right'
|
|
||||||
#z.legend.visible = False
|
|
||||||
z.axis.visible = False
|
|
||||||
z.xgrid.grid_line_color = None
|
|
||||||
z.ygrid.grid_line_color = None
|
|
||||||
z.outline_line_color = None
|
|
||||||
|
|
||||||
return components(z)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,8 @@
|
|||||||
<input type="submit" value="Submit"/>
|
<input type="submit" value="Submit"/>
|
||||||
</form>
|
</form>
|
||||||
</p>
|
</p>
|
||||||
|
</li>
|
||||||
|
<li class="grid_2">
|
||||||
<h2>All workouts</h2>
|
<h2>All workouts</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@@ -56,7 +58,7 @@
|
|||||||
<td>Total Distance</td><td>{{ totalsdict|lookup:"distance"}} meters</td>
|
<td>Total Distance</td><td>{{ totalsdict|lookup:"distance"}} meters</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Total Duration</td><td>{{ totalsdict|lookup:"duration"}} hours</td>
|
<td>Total Duration</td><td>{{ totalsdict|lookup:"duration"}} </td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Number of workouts</td><td>{{ totalsdict|lookup:"nrworkouts"}}</td>
|
<td>Number of workouts</td><td>{{ totalsdict|lookup:"nrworkouts"}}</td>
|
||||||
@@ -97,7 +99,7 @@
|
|||||||
<td>Total Distance</td><td>{{ ddict|lookup:"distance"}} meters</td>
|
<td>Total Distance</td><td>{{ ddict|lookup:"distance"}} meters</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Total Duration</td><td>{{ ddict|lookup:"duration"}} hours</td>
|
<td>Total Duration</td><td>{{ ddict|lookup:"duration"}} </td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Number of workouts</td><td>{{ ddict|lookup:"nrworkouts"}}</td>
|
<td>Number of workouts</td><td>{{ ddict|lookup:"nrworkouts"}}</td>
|
||||||
|
|||||||
@@ -4699,7 +4699,7 @@ def history_view(request,userid=0):
|
|||||||
|
|
||||||
tscript,tdiv = interactive_workouttype_piechart(g_workouts)
|
tscript,tdiv = interactive_workouttype_piechart(g_workouts)
|
||||||
|
|
||||||
totalmeters,totalhours, totalminutes = get_totals(g_workouts)
|
totalmeters,totalhours, totalminutes, totalseconds = get_totals(g_workouts)
|
||||||
totalminutes = "{totalminutes:02d}".format(totalminutes=totalminutes)
|
totalminutes = "{totalminutes:02d}".format(totalminutes=totalminutes)
|
||||||
|
|
||||||
# meters, duration per workout type
|
# meters, duration per workout type
|
||||||
@@ -4716,7 +4716,7 @@ def history_view(request,userid=0):
|
|||||||
|
|
||||||
for wtype in wtypes:
|
for wtype in wtypes:
|
||||||
a_workouts = g_workouts.filter(workouttype=wtype)
|
a_workouts = g_workouts.filter(workouttype=wtype)
|
||||||
wmeters, whours, wminutes = get_totals(a_workouts)
|
wmeters, whours, wminutes,wseconds = get_totals(a_workouts)
|
||||||
ddict = {}
|
ddict = {}
|
||||||
ddict['id'] = wtype
|
ddict['id'] = wtype
|
||||||
try:
|
try:
|
||||||
@@ -4724,9 +4724,10 @@ def history_view(request,userid=0):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
ddict['wtype'] = wtype
|
ddict['wtype'] = wtype
|
||||||
ddict['distance'] = wmeters
|
ddict['distance'] = wmeters
|
||||||
ddict['duration'] = "{whours}:{wminutes:02d}".format(
|
ddict['duration'] = "{whours}:{wminutes:02d}:{wseconds:02d}".format(
|
||||||
whours=whours,
|
whours=whours,
|
||||||
wminutes=wminutes
|
wminutes=wminutes,
|
||||||
|
wseconds=wseconds,
|
||||||
)
|
)
|
||||||
ddict['nrworkouts'] = a_workouts.count()
|
ddict['nrworkouts'] = a_workouts.count()
|
||||||
listofdicts.append(ddict)
|
listofdicts.append(ddict)
|
||||||
@@ -4737,9 +4738,10 @@ def history_view(request,userid=0):
|
|||||||
totaldiv = get_call()
|
totaldiv = get_call()
|
||||||
|
|
||||||
totalsdict = {}
|
totalsdict = {}
|
||||||
totalsdict['duration'] = "{totalhours}:{totalminutes}".format(
|
totalsdict['duration'] = "{totalhours}:{totalminutes}:{totalseconds}".format(
|
||||||
totalhours=totalhours,
|
totalhours=totalhours,
|
||||||
totalminutes=totalminutes
|
totalminutes=totalminutes,
|
||||||
|
totalseconds=totalseconds
|
||||||
)
|
)
|
||||||
|
|
||||||
totalsdict['distance'] = totalmeters
|
totalsdict['distance'] = totalmeters
|
||||||
@@ -4836,7 +4838,7 @@ def history_view_data(request,userid=0):
|
|||||||
df = dataprep.clean_df_stats(df,workstrokesonly=True,
|
df = dataprep.clean_df_stats(df,workstrokesonly=True,
|
||||||
ignoreadvanced=True)
|
ignoreadvanced=True)
|
||||||
|
|
||||||
totalmeters,totalhours, totalminutes = get_totals(g_workouts)
|
totalmeters,totalhours, totalminutes,totalseconds = get_totals(g_workouts)
|
||||||
totalminutes = "{totalminutes:02d}".format(totalminutes=totalminutes)
|
totalminutes = "{totalminutes:02d}".format(totalminutes=totalminutes)
|
||||||
|
|
||||||
|
|
||||||
@@ -4853,7 +4855,7 @@ def history_view_data(request,userid=0):
|
|||||||
|
|
||||||
for wtype in wtypes:
|
for wtype in wtypes:
|
||||||
a_workouts = g_workouts.filter(workouttype=wtype)
|
a_workouts = g_workouts.filter(workouttype=wtype)
|
||||||
wmeters, whours, wminutes = get_totals(a_workouts)
|
wmeters, whours, wminutes,wseconds = get_totals(a_workouts)
|
||||||
ddict = {}
|
ddict = {}
|
||||||
try:
|
try:
|
||||||
ddict['wtype'] = mytypes.workouttypes_ordered[wtype]
|
ddict['wtype'] = mytypes.workouttypes_ordered[wtype]
|
||||||
@@ -4862,9 +4864,9 @@ def history_view_data(request,userid=0):
|
|||||||
|
|
||||||
ddict['id'] = wtype
|
ddict['id'] = wtype
|
||||||
ddict['distance'] = wmeters
|
ddict['distance'] = wmeters
|
||||||
ddict['duration'] = "{whours}:{wminutes:02d}".format(
|
ddict['duration'] = "{whours}:{wminutes:02d}:{wseconds:02d}".format(
|
||||||
whours=whours,
|
whours=whours,
|
||||||
wminutes=wminutes
|
wminutes=wminutes,wseconds=wseconds,
|
||||||
)
|
)
|
||||||
ddf = getsmallrowdata_db(columns,ids=[w.id for w in a_workouts])
|
ddf = getsmallrowdata_db(columns,ids=[w.id for w in a_workouts])
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -260,16 +260,17 @@ from django_mailbox.models import Message,Mailbox,MessageAttachment
|
|||||||
from rules.contrib.views import permission_required, objectgetter
|
from rules.contrib.views import permission_required, objectgetter
|
||||||
|
|
||||||
def get_totals(workouts):
|
def get_totals(workouts):
|
||||||
totalminutes = 0
|
totalseconds = 0
|
||||||
totalmeters = 0
|
totalmeters = 0
|
||||||
|
|
||||||
for w in workouts:
|
for w in workouts:
|
||||||
totalmeters += w.distance
|
totalmeters += w.distance
|
||||||
totalminutes += w.duration.hour*60+w.duration.minute
|
totalseconds += 60*(w.duration.hour*60+w.duration.minute)+w.duration.second
|
||||||
|
|
||||||
totalhour, totalminutes = divmod(totalminutes,60)
|
hours, remainder = divmod(totalseconds,3600)
|
||||||
|
minutes, seconds = divmod(remainder,60)
|
||||||
|
|
||||||
return totalmeters,totalhour, totalminutes
|
return totalmeters,hours, minutes, seconds
|
||||||
|
|
||||||
# creating shareable views
|
# creating shareable views
|
||||||
def allow_shares(view_func):
|
def allow_shares(view_func):
|
||||||
|
|||||||
Reference in New Issue
Block a user