Merge branch 'feature/multiflexcolors' into develop
This commit is contained in:
+9
-1
@@ -327,6 +327,11 @@ formaxlabelsmultiflex.pop('distance')
|
|||||||
formaxlabelsmultiflex['workoutid'] = 'Workout'
|
formaxlabelsmultiflex['workoutid'] = 'Workout'
|
||||||
parchoicesmultiflex = list(sorted(formaxlabelsmultiflex.items(), key = lambda x:x[1]))
|
parchoicesmultiflex = list(sorted(formaxlabelsmultiflex.items(), key = lambda x:x[1]))
|
||||||
|
|
||||||
|
from utils import palettes
|
||||||
|
#palettechoices = { key:key for key, value in palettes.iteritems() }
|
||||||
|
|
||||||
|
palettechoices = tuple((p,p) for p in palettes.keys())
|
||||||
|
|
||||||
|
|
||||||
class MultiFlexChoiceForm(forms.Form):
|
class MultiFlexChoiceForm(forms.Form):
|
||||||
xparam = forms.ChoiceField(choices=parchoicesmultiflex,
|
xparam = forms.ChoiceField(choices=parchoicesmultiflex,
|
||||||
@@ -352,7 +357,10 @@ class MultiFlexChoiceForm(forms.Form):
|
|||||||
includereststrokes = forms.BooleanField(initial=False,
|
includereststrokes = forms.BooleanField(initial=False,
|
||||||
required=False,
|
required=False,
|
||||||
label='Include Rest Strokes')
|
label='Include Rest Strokes')
|
||||||
|
palette = forms.ChoiceField(choices=palettechoices,
|
||||||
|
label = 'Color Scheme',
|
||||||
|
initial='monochrome_blue')
|
||||||
|
|
||||||
class ChartParamChoiceForm(forms.Form):
|
class ChartParamChoiceForm(forms.Form):
|
||||||
plotchoices = (
|
plotchoices = (
|
||||||
('line','Line Plot'),
|
('line','Line Plot'),
|
||||||
|
|||||||
+57
-14
@@ -1,3 +1,4 @@
|
|||||||
|
import colorsys
|
||||||
from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage
|
from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage
|
||||||
from rowingdata import rower as rrower
|
from rowingdata import rower as rrower
|
||||||
from rowingdata import main as rmain
|
from rowingdata import main as rmain
|
||||||
@@ -10,7 +11,7 @@ from django.utils import timezone
|
|||||||
from bokeh.palettes import Dark2_8 as palette
|
from bokeh.palettes import Dark2_8 as palette
|
||||||
import itertools
|
import itertools
|
||||||
from bokeh.plotting import figure, ColumnDataSource, Figure,curdoc
|
from bokeh.plotting import figure, ColumnDataSource, Figure,curdoc
|
||||||
from bokeh.models import CustomJS,Slider, TextInput
|
from bokeh.models import CustomJS,Slider, TextInput,BoxAnnotation
|
||||||
from bokeh.charts import Histogram,HeatMap,Area,BoxPlot
|
from bokeh.charts import Histogram,HeatMap,Area,BoxPlot
|
||||||
from bokeh.resources import CDN,INLINE
|
from bokeh.resources import CDN,INLINE
|
||||||
from bokeh.embed import components
|
from bokeh.embed import components
|
||||||
@@ -70,11 +71,9 @@ watermarkh = 35
|
|||||||
watermarkanchor = 'bottom_right'
|
watermarkanchor = 'bottom_right'
|
||||||
|
|
||||||
def errorbar(fig, x, y, source=ColumnDataSource(),
|
def errorbar(fig, x, y, source=ColumnDataSource(),
|
||||||
xerr=False, yerr=False, color='red',
|
xerr=False, yerr=False, color='black',
|
||||||
point_kwargs={}, error_kwargs={}):
|
point_kwargs={}, error_kwargs={}):
|
||||||
|
|
||||||
fig.circle(x, y, source=source, name='data',color=color,
|
|
||||||
**point_kwargs)
|
|
||||||
|
|
||||||
xvalues = source.data[x]
|
xvalues = source.data[x]
|
||||||
yvalues = source.data[y]
|
yvalues = source.data[y]
|
||||||
@@ -96,7 +95,12 @@ def errorbar(fig, x, y, source=ColumnDataSource(),
|
|||||||
for px, py, err, color in zip(xvalues, yvalues, xerrvalues, colorvalues):
|
for px, py, err, color in zip(xvalues, yvalues, xerrvalues, colorvalues):
|
||||||
x_err_x.append((px - err, px + err))
|
x_err_x.append((px - err, px + err))
|
||||||
x_err_y.append((py, py))
|
x_err_y.append((py, py))
|
||||||
err_color.append(color)
|
(r, g, b) = tuple(int(color[i:i+2],16) for i in (1, 3, 5))
|
||||||
|
h,s,v = colorsys.rgb_to_hsv(r/255., g/255., b/255.)
|
||||||
|
v = v*0.8
|
||||||
|
r, g, b = colorsys.hsv_to_rgb(h, s, v)
|
||||||
|
color2 = "#%02x%02x%02x" % (int(255.*r), int(255.*g), int(255*b))
|
||||||
|
err_color.append(color2)
|
||||||
|
|
||||||
fig.multi_line(x_err_x, x_err_y, color=err_color,
|
fig.multi_line(x_err_x, x_err_y, color=err_color,
|
||||||
name='xerr',
|
name='xerr',
|
||||||
@@ -113,13 +117,22 @@ def errorbar(fig, x, y, source=ColumnDataSource(),
|
|||||||
for px, py, err, color in zip(xvalues, yvalues, yerrvalues, colorvalues):
|
for px, py, err, color in zip(xvalues, yvalues, yerrvalues, colorvalues):
|
||||||
y_err_x.append((px, px))
|
y_err_x.append((px, px))
|
||||||
y_err_y.append((py - err, py + err))
|
y_err_y.append((py - err, py + err))
|
||||||
err_color.append(color)
|
(r, g, b) = tuple(int(color[i:i+2],16) for i in (1, 3, 5))
|
||||||
|
h,s,v = colorsys.rgb_to_hsv(r/255., g/255., b/255.)
|
||||||
|
v = v*0.8
|
||||||
|
r, g, b = colorsys.hsv_to_rgb(h, s, v)
|
||||||
|
color2 = "#%02x%02x%02x" % (int(255.*r), int(255.*g), int(255*b))
|
||||||
|
err_color.append(color2)
|
||||||
|
|
||||||
fig.multi_line(y_err_x, y_err_y, color=err_color,
|
fig.multi_line(y_err_x, y_err_y, color=err_color,
|
||||||
name='yerr',**error_kwargs)
|
name='yerr',**error_kwargs)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
fig.circle(x, y, source=source, name='data',color=color,
|
||||||
|
**point_kwargs)
|
||||||
|
|
||||||
|
|
||||||
def tailwind(bearing,vwind,winddir):
|
def tailwind(bearing,vwind,winddir):
|
||||||
""" Calculates head-on head/tailwind in direction of rowing
|
""" Calculates head-on head/tailwind in direction of rowing
|
||||||
|
|
||||||
@@ -1176,7 +1189,7 @@ def interactive_chart(id=0,promember=0):
|
|||||||
|
|
||||||
def interactive_multiflex(datadf,xparam,yparam,groupby,extratitle='',
|
def interactive_multiflex(datadf,xparam,yparam,groupby,extratitle='',
|
||||||
ploterrorbars=False,
|
ploterrorbars=False,
|
||||||
title=None,binsize=1):
|
title=None,binsize=1,colorlegend=[]):
|
||||||
|
|
||||||
if datadf.empty:
|
if datadf.empty:
|
||||||
return ['','<p>No non-zero data in selection</p>']
|
return ['','<p>No non-zero data in selection</p>']
|
||||||
@@ -1246,18 +1259,17 @@ def interactive_multiflex(datadf,xparam,yparam,groupby,extratitle='',
|
|||||||
datadf,
|
datadf,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize'
|
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize'
|
||||||
|
|
||||||
if groupby != 'date':
|
if groupby != 'date':
|
||||||
hover = HoverTool(names=['data'],
|
hover = HoverTool(names=['data'],
|
||||||
tooltips = [
|
tooltips = [
|
||||||
(groupby,'@groupval{1.1}')
|
(groupby,'@groupval{1.1}'),
|
||||||
])
|
])
|
||||||
else:
|
else:
|
||||||
hover = HoverTool(names=['data'],
|
hover = HoverTool(names=['data'],
|
||||||
tooltips = [
|
tooltips = [
|
||||||
(groupby,'@groupval')
|
(groupby,'@groupval'),
|
||||||
])
|
])
|
||||||
|
|
||||||
hover.mode = 'mouse'
|
hover.mode = 'mouse'
|
||||||
@@ -1268,7 +1280,7 @@ def interactive_multiflex(datadf,xparam,yparam,groupby,extratitle='',
|
|||||||
plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
|
plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
|
||||||
tools=TOOLS,
|
tools=TOOLS,
|
||||||
toolbar_location="above",
|
toolbar_location="above",
|
||||||
toolbar_sticky=False)
|
toolbar_sticky=False) #,plot_width=500,plot_height=500)
|
||||||
|
|
||||||
# add watermark
|
# add watermark
|
||||||
plot.extra_y_ranges = {"watermark": watermarkrange}
|
plot.extra_y_ranges = {"watermark": watermarkrange}
|
||||||
@@ -1287,17 +1299,48 @@ def interactive_multiflex(datadf,xparam,yparam,groupby,extratitle='',
|
|||||||
x_range_name = "watermark",
|
x_range_name = "watermark",
|
||||||
y_range_name = "watermark",
|
y_range_name = "watermark",
|
||||||
)
|
)
|
||||||
|
|
||||||
errorbar(plot,xparam,yparam,source=source,
|
errorbar(plot,xparam,yparam,source=source,
|
||||||
xerr=ploterrorbars,
|
xerr=ploterrorbars,
|
||||||
yerr=ploterrorbars,
|
yerr=ploterrorbars,
|
||||||
point_kwargs={
|
point_kwargs={
|
||||||
'line_color':None,
|
'line_color':"#969696",
|
||||||
'size':"groupsize",
|
'size':"groupsize",
|
||||||
'fill_color':"color",
|
'fill_color':"color",
|
||||||
|
'fill_alpha':1.0,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for nr, gvalue, color in colorlegend:
|
||||||
|
box = BoxAnnotation(bottom=500-20*nr,left=550,top=520-20*nr,
|
||||||
|
right=570,
|
||||||
|
bottom_units='screen',
|
||||||
|
top_units='screen',
|
||||||
|
left_units='screen',
|
||||||
|
right_units='screen',
|
||||||
|
fill_color=color,
|
||||||
|
fill_alpha=1.0,
|
||||||
|
line_color=color)
|
||||||
|
legendlabel = Label(x=571,y=503-20*nr,x_units='screen',
|
||||||
|
y_units='screen',
|
||||||
|
text = "{gvalue:3.0f}".format(gvalue=gvalue),
|
||||||
|
background_fill_alpha=1.0,
|
||||||
|
text_color='black',
|
||||||
|
text_font_size=value("0.7em"))
|
||||||
|
plot.add_layout(box)
|
||||||
|
plot.add_layout(legendlabel)
|
||||||
|
|
||||||
|
if colorlegend:
|
||||||
|
legendlabel = Label(x=372,y=300,x_units='screen',
|
||||||
|
y_units='screen',
|
||||||
|
text = 'group legend',
|
||||||
|
text_color='black',
|
||||||
|
text_font_size=value("0.7em"),
|
||||||
|
angle=90,
|
||||||
|
angle_units='deg')
|
||||||
|
|
||||||
if xparam == 'workoutid':
|
if xparam == 'workoutid':
|
||||||
plot.xaxis.axis_label = 'Workout'
|
plot.xaxis.axis_label = 'Workout'
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,9 +1,59 @@
|
|||||||
import math
|
import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
import colorsys
|
||||||
|
|
||||||
lbstoN = 4.44822
|
lbstoN = 4.44822
|
||||||
|
|
||||||
|
def trcolors(r1,g1,b1,r2,g2,b2):
|
||||||
|
r1 = r1/255.
|
||||||
|
r2 = r2/255.
|
||||||
|
g1 = g1/255.
|
||||||
|
g2 = g2/255.
|
||||||
|
b2 = b2/255.
|
||||||
|
b1 = b1/255.
|
||||||
|
h1,s1,v1 = colorsys.rgb_to_hsv(r1,g1,b1)
|
||||||
|
h2,s2,v2 = colorsys.rgb_to_hsv(r2,g2,b2)
|
||||||
|
|
||||||
|
|
||||||
|
return 360*h1,360*(h2-h1),s1,(s2-s1),v1,(v2-v1)
|
||||||
|
|
||||||
|
palettes = {
|
||||||
|
'monochrome_blue':(207,-4,0.06,0.89,1.0,-0.38),
|
||||||
|
'gold_sunset':(47,-31,.26,-0.12,0.94,-0.5),
|
||||||
|
'blue_red':(207,-200,.85,0,.74,-.24),
|
||||||
|
'blue_green':(207,-120,.85,0,.75,.25),
|
||||||
|
'cyan_green':(192,-50,.08,.65,.98,-.34),
|
||||||
|
'cyan_purple':trcolors(237,248,251,136,65,157),
|
||||||
|
'green_blue':trcolors(240,249,232,8,104,172),
|
||||||
|
'orange_red':trcolors(254,240,217,179,0,0),
|
||||||
|
'cyan_blue':trcolors(241,238,246,4,90,141),
|
||||||
|
'cyan_green':trcolors(246,239,247,1,108,89),
|
||||||
|
'cyan_magenta':trcolors(241,238,246,152,0,67),
|
||||||
|
'beige_magenta':trcolors(254,235,226,122,1,119),
|
||||||
|
'yellow_green':trcolors(255,255,204,0,104,55),
|
||||||
|
'yellow_blue':trcolors(255,255,205,37,52,148),
|
||||||
|
'autumn':trcolors(255,255,212,153,52,4),
|
||||||
|
'yellow_red':trcolors(255,255,178,189,0,39)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def range_to_color_hex(groupcols,palette='monochrome_blue'):
|
||||||
|
|
||||||
|
try:
|
||||||
|
plt = palettes[palette]
|
||||||
|
except KeyErro:
|
||||||
|
plt = palettes['monochrome_blue']
|
||||||
|
|
||||||
|
rgb = [colorsys.hsv_to_rgb((plt[0]+plt[1]*x)/360.,
|
||||||
|
plt[2]+plt[3]*x,
|
||||||
|
plt[4]+plt[5]*x) for x in groupcols]
|
||||||
|
|
||||||
|
RGB = [(int(255.*r),int(255.*g),int(255.*b)) for (r, g, b) in rgb]
|
||||||
|
colors = ["#%02x%02x%02x" % (r, g, b) for (r, g, b) in RGB]
|
||||||
|
|
||||||
|
return colors
|
||||||
|
|
||||||
def str2bool(v):
|
def str2bool(v):
|
||||||
return v.lower() in ("yes", "true", "t", "1")
|
return v.lower() in ("yes", "true", "t", "1")
|
||||||
|
|
||||||
|
|||||||
+30
-10
@@ -272,7 +272,7 @@ def splitstdata(lijst):
|
|||||||
|
|
||||||
from utils import (
|
from utils import (
|
||||||
geo_distance,serialize_list,deserialize_list,uniqify,
|
geo_distance,serialize_list,deserialize_list,uniqify,
|
||||||
str2bool
|
str2bool,range_to_color_hex
|
||||||
)
|
)
|
||||||
|
|
||||||
import datautils
|
import datautils
|
||||||
@@ -3435,6 +3435,11 @@ def multiflex_view(request,userid=0,
|
|||||||
ploterrorbars = options['ploterrorbars']
|
ploterrorbars = options['ploterrorbars']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
ploterrorbars = False
|
ploterrorbars = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
palette = options['palette']
|
||||||
|
except KeyError:
|
||||||
|
palette = 'blue_green'
|
||||||
|
|
||||||
workstrokesonly = not includereststrokes
|
workstrokesonly = not includereststrokes
|
||||||
|
|
||||||
@@ -3454,7 +3459,9 @@ def multiflex_view(request,userid=0,
|
|||||||
request.session['ploterrorbars'] = ploterrorbars
|
request.session['ploterrorbars'] = ploterrorbars
|
||||||
request.session['includereststrokes'] = includereststrokes
|
request.session['includereststrokes'] = includereststrokes
|
||||||
workstrokesonly = not includereststrokes
|
workstrokesonly = not includereststrokes
|
||||||
|
palette = chartform.cleaned_data['palette']
|
||||||
|
request.session['palette'] = palette
|
||||||
|
|
||||||
groupby = chartform.cleaned_data['groupby']
|
groupby = chartform.cleaned_data['groupby']
|
||||||
binsize = chartform.cleaned_data['binsize']
|
binsize = chartform.cleaned_data['binsize']
|
||||||
if binsize <= 0:
|
if binsize <= 0:
|
||||||
@@ -3482,6 +3489,8 @@ def multiflex_view(request,userid=0,
|
|||||||
request.session['ploterrorbars'] = ploterrorbars
|
request.session['ploterrorbars'] = ploterrorbars
|
||||||
request.session['includereststrokes'] = includereststrokes
|
request.session['includereststrokes'] = includereststrokes
|
||||||
workstrokesonly = not includereststrokes
|
workstrokesonly = not includereststrokes
|
||||||
|
palette = chartform.cleaned_data['palette']
|
||||||
|
request.session['palette'] = palette
|
||||||
|
|
||||||
groupby = chartform.cleaned_data['groupby']
|
groupby = chartform.cleaned_data['groupby']
|
||||||
binsize = chartform.cleaned_data['binsize']
|
binsize = chartform.cleaned_data['binsize']
|
||||||
@@ -3570,9 +3579,12 @@ def multiflex_view(request,userid=0,
|
|||||||
yerror = groups.std()[yparam]
|
yerror = groups.std()[yparam]
|
||||||
groupsize = groups.count()[xparam]
|
groupsize = groups.count()[xparam]
|
||||||
|
|
||||||
#groupsize = 15.*np.log10(1+99.*groupsize/float(max(groupsize)))
|
if len(groupsize) == 0:
|
||||||
groupsize = 30.*np.sqrt(groupsize/float(max(groupsize)))
|
messages.error(request,'No data in selection')
|
||||||
|
url = reverse(user_multiflex_select)
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
else:
|
||||||
|
groupsize = 30.*np.sqrt(groupsize/float(groupsize.max()))
|
||||||
|
|
||||||
df = pd.DataFrame({
|
df = pd.DataFrame({
|
||||||
xparam:xvalues,
|
xparam:xvalues,
|
||||||
@@ -3604,12 +3616,19 @@ def multiflex_view(request,userid=0,
|
|||||||
if aantal == 1:
|
if aantal == 1:
|
||||||
groupcols = np.array([1.])
|
groupcols = np.array([1.])
|
||||||
|
|
||||||
groupcols *= 100.
|
|
||||||
rgb = [colorsys.hsv_to_rgb(float(x/100.), 1.0, 1.0) for x in groupcols]
|
colors = range_to_color_hex(groupcols,palette=palette)
|
||||||
RGB = [(int(255.*r),int(255.*g),int(255.*b)) for (r, g, b) in rgb]
|
|
||||||
colors = ["#%02x%02x%02x" % (r, g, b) for (r, g, b) in RGB]
|
|
||||||
df['color'] = colors
|
df['color'] = colors
|
||||||
|
|
||||||
|
clegendx = np.arange(0,1.2,.2)
|
||||||
|
legcolors = range_to_color_hex(clegendx,palette=palette)
|
||||||
|
clegendy = df['groupval'].min()+clegendx*(df['groupval'].max()-df['groupval'].min())
|
||||||
|
|
||||||
|
|
||||||
|
colorlegend = zip(range(6),clegendy,legcolors)
|
||||||
|
|
||||||
|
|
||||||
if userid == 0:
|
if userid == 0:
|
||||||
extratitle = ''
|
extratitle = ''
|
||||||
else:
|
else:
|
||||||
@@ -3622,7 +3641,8 @@ def multiflex_view(request,userid=0,
|
|||||||
groupby,
|
groupby,
|
||||||
extratitle=extratitle,
|
extratitle=extratitle,
|
||||||
ploterrorbars=ploterrorbars,
|
ploterrorbars=ploterrorbars,
|
||||||
binsize=binsize)
|
binsize=binsize,
|
||||||
|
colorlegend=colorlegend)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user