1313
1414from bokeh .transform import dodge
1515
16- # for tests
17- #import pandas as pd
18- #import random
19- #from bokeh.io import output_notebook, show, push_notebook
20-
21- #x = [str(i) for i in range(7)]
22- #xs = [x,x,x,x,x]
23- #xlabels = [[f'1 pli bla blub {i}' for i in x], [f'2 pli bla blub {i}' for i in x], [f'3 pli bla blub {i}' for i in x], [f'4 pli bla blub {i}' for i in x], [f'5 pli bla blub {i}' for i in x]]
24- #ys = [[random.randint(0, 1200) for i in x], [random.randint(0, 1200) for i in x], [random.randint(0, 1200) for i in x],[random.randint(0, 1200) for i in x], [random.randint(0, 1200) for i in x]]
25-
26- # bokeh bar plot
27- '''
28- def bokeh_barchart(df, x='value', y='counts', factors=None, figure=None, title='This is a title', width=0.9, xlabel='Answers', ylabel='Number of answers', palette=Category20c, fill_color='color', description='For more information about the HMC survey click here.', redirect='https://helmholtz-metadaten.de/en/pages/structure-governance'):
29- """Plot an interactive bar chart with bokeh"""
30- legend_it = []
31- if isinstance(df, ColumnDataSource):
32- xdata = df.data[x]
33- if not 'color' in df.column_names:
34- if not len(xdata) > 20:
35- df.data['color'] = Category20c[len(xdata)] # ! if len(xdata)>20 this fails
36- else:
37- xdata = df[x]
38- if not 'color' in df.columns:
39- df['color'] = Category20c[len(xdata)] # ! if len(xdata)>20 this fails
40-
41- help_t = HelpTool(description=description, redirect=redirect)
42-
43- tools = 'hover,wheel_zoom,box_zoom,undo,reset,save'
44- if figure is None:
45- if factors is not None:
46- fig = bokeh_figure(plot_height=600, plot_width=600,
47- title=title,
48- toolbar_location='above',
49- x_range=FactorRange(factors=factors),
50- tools=tools,#'hover',
51- tooltips=[('Data', f'@{x}'), ('Count', f'@{y}')])
52- else:
53- fig = bokeh_figure(plot_height=600, plot_width=600,
54- title=title,
55- toolbar_location='above',
56- tools=tools,#'hover',
57- tooltips=[('Data', f'@{x}'), ('Count', f'@{y}')])
58- else:
59- fig = figure
60- #if factors is not None:
61- # fig.x_range=FactorRange(factors=factors)
62-
63- fig.add_tools(help_t)
64- fig.vbar(x=x, top=y, width=width, source=df, line_color="white", fill_color=fill_color)#factor_cmap('x', palette=palette, factors=factors, start=1, end=2))
65- fig.y_range.start = 0
66- fig.x_range.range_padding = 0.1
67- fig.toolbar.logo = None
68- fig.xaxis.major_label_orientation = 1
69- fig.xgrid.grid_line_color = None
70- fig.yaxis.axis_label = ylabel
71- fig.xaxis.axis_label = xlabel
72- fig.xgrid.grid_line_color = None
73-
74-
75- #fig.legend.location = "left"
76- #fig.legend.orientation = "horizontal"
77- #fig.legend.click_policy="hide"
78-
79- return fig
80-
81- def bokeh_barchart2(df, x=['value'], y=['counts'], factors=None, figure=None, data_visible=[True], title='', width=0.9, xlabel='Answers', ylabel='Number of answers', palette=Category20c, fill_color='color', legend_labels=None):
82- """Plot an interactive bar chart with bokeh"""
83-
84- if figure is None:
85- if factors is not None:
86- fig = bokeh_figure(plot_height=600, plot_width=600,
87- title=title,
88- toolbar_location='above',
89- #x_range=FactorRange(factors=factors),
90- tools='',#'hover',
91- tooltips=[('Data', f'@{x}'), ('Count', f'@{y}')])
92- else:
93- fig = bokeh_figure(plot_height=600, plot_width=600,
94- title=title,
95- toolbar_location='above',
96- tools='',#'hover',
97- tooltips=[('Data', f'@{x}'), ('Count', f'@{y}')])
98- else:
99- fig = figure
100-
101- if isinstance(x, list):
102- if not 'color' in df.column_names:
103- if isinstance(palette, dict):
104- x_color = palette[len(x)]
105- else:
106- x_color = df.data['color']
107- position = []
108- step = width + 0.05
109- nvisible = data_visible.count(True)
110- if nvisible%2 == 0:
111- start = -step*nvisible/2 + step/2.0
112- elif nvisible==1:
113- start = 0.0
114- else:
115- start = nvisible//2 * -step
116- displayed_pos = [start + i*step for i in range(nvisible)]
117- ind = 0
118- for visible in data_visible:
119- if not visible:
120- position.append(0.0)
121- else:
122- position.append(displayed_pos[ind])
123- ind = ind+1
124- for i, data in enumerate(x):
125- fig.vbar(x=dodge(data, position[i], range=fig.x_range), top=y[i], source=df,
126- width=width, color=x_color[i], legend_label=data, visible=data_visible[i])
127- else:
128- if isinstance(df, ColumnDataSource):
129- xdata = df.data[x]
130- if not 'color' in df.column_names:
131- df.data['color'] = palette[len(xdata)]
132- else:
133- xdata = df[x]
134- if not 'color' in df.columns:
135- df['color'] = palette[len(xdata)]
136- fig.vbar(x=x, top=y, width=width, source=df, line_color="white", fill_color=fill_color)#factor_cmap('x', palette=palette, factors=factors, start=1, end=2))
137-
138- fig.y_range.start = 0
139- fig.x_range.range_padding = 0.1
140- fig.xaxis.major_label_orientation = 1
141- fig.xgrid.grid_line_color = None
142- fig.yaxis.axis_label = ylabel
143- fig.xaxis.axis_label = xlabel
144- fig.xgrid.grid_line_color = None
145-
146- fig.toolbar.logo = None
147- #fig.legend.location = "left"
148- #fig.legend.orientation = "horizontal"
149- #fig.legend.click_policy="hide"
150-
151- return fig
152- '''
15316
15417def add_legend_outside (fig ):
15518 """
@@ -161,6 +24,8 @@ def add_legend_outside(fig):
16124 legend = fig .legend
16225 fig .add_layout (legend , 'right' )
16326 return fig
27+
28+
16429# test
16530#df_test = pd.DataFrame(data=dict(value=xs[0], counts=ys[0]))
16631#fig = bokeh_barchart(df_test, factors=xs[0])
@@ -173,12 +38,66 @@ def add_legend_outside(fig):
17338#palette = Category20c[len(ys[0])]
17439#fig = bokeh_barchart(df_test3, factors=factors, fill_color=factor_cmap('value', palette=palette, factors=xs[0], start=1, end=2))
17540#show(fig)
41+ def preprocess_bokeh_input (func ):
42+ """Decorator function to preprocess, modify any bokeh plotting functions
43+
44+ :param func: the function to be decorated
45+ :type func: function
46+ """
47+ def modified_plot (* args , ** kwargs ):
48+ """Modifed plot functions"""
49+
50+ # check if pandas data frame, if yes convert
51+ # figure_kwargs
52+ # plot function kwargs
53+ func (* args , ** kwargs )
54+
17655
56+ return modified_plot
17757
58+
59+ @preprocess_bokeh_input
17860def bokeh_barchart (df , x = 'x_value' , y = ['y_value' ], factors = None , figure = None , data_visible = [True ], title = '' ,
17961 width = 0.1 , xlabel = '' , ylabel = 'Number of answers' , palette = Category20c ,
180- fill_color = None , legend_labels = None , description = 'For more information about the HMC survey click here.' , redirect = 'https://helmholtz-metadaten.de/en/pages/structure-governance' ):
62+ fill_color = None , legend_labels = None , description = 'For more information about the HMC survey click here.' ,
63+ redirect = 'https://helmholtz-metadaten.de/en/pages/structure-governance' , ** kwargs ):
64+ """Create an interactive bar chart with bokeh
65+
66+ :param df: [description]
67+ :type df: bokeh.models.ColumnDataSource
68+ :param x: [description], defaults to 'x_value'
69+ :type x: str, optional
70+ :param y: [description], defaults to ['y_value']
71+ :type y: list, optional
72+ :param factors: [description], defaults to None
73+ :type factors: [type], optional
74+ :param figure: [description], defaults to None
75+ :type figure: [type], optional
76+ :param data_visible: [description], defaults to [True]
77+ :type data_visible: list, optional
78+ :param title: [description], defaults to ''
79+ :type title: str, optional
80+ :param width: [description], defaults to 0.1
81+ :type width: float, optional
82+ :param xlabel: [description], defaults to ''
83+ :type xlabel: str, optional
84+ :param ylabel: [description], defaults to 'Number of answers'
85+ :type ylabel: str, optional
86+ :param palette: [description], defaults to Category20c
87+ :type palette: [type], optional
88+ :param fill_color: [description], defaults to None
89+ :type fill_color: [type], optional
90+ :param legend_labels: [description], defaults to None
91+ :type legend_labels: [type], optional
92+ :param description: [description], defaults to 'For more information about the HMC survey click here.'
93+ :type description: str, optional
94+ :param redirect: [description], defaults to 'https://helmholtz-metadaten.de/en/pages/structure-governance'
95+ :type redirect: str, optional
96+ :return: [description]
97+ :rtype: [type]
98+ """
18199 y_keys = y
100+
182101 source = df
183102
184103 help_t = HelpTool (description = description , redirect = redirect )
@@ -202,7 +121,7 @@ def bokeh_barchart(df, x='x_value', y=['y_value'], factors=None, figure=None, da
202121 bars = []
203122 for i , y in enumerate (y_keys ):
204123 bar = fig .vbar (x = dodge (x , position [i ], range = fig .x_range ), top = y , source = source ,
205- width = width , color = fill_color [i ], legend_label = y )
124+ width = width , color = fill_color [i ], legend_label = y , ** kwargs )
206125 tooltips .append ((f'{ y } ' , '@{' + str (y ) + '}' ))
207126 bars .append (bar )
208127
@@ -226,8 +145,9 @@ def bokeh_barchart(df, x='x_value', y=['y_value'], factors=None, figure=None, da
226145
227146
228147
229- # bokeh piechart
230- def bokeh_piechart (df , x = 'value' , y = 'counts' , figure = None , radius = 0.8 , title = '' ):
148+ # bokeh piechart
149+ @preprocess_bokeh_input
150+ def bokeh_piechart (df , x = 'value' , y = 'counts' , figure = None , radius = 0.8 , title = '' , ** kwargs ):
231151 """Draw an interactive piechart with bokeh"""
232152
233153 from math import pi
@@ -265,7 +185,7 @@ def bokeh_piechart(df, x='value', y='counts', figure=None, radius=0.8, title='')
265185 line_color = 'white' ,
266186 fill_color = 'color' ,
267187 legend_field = x ,
268- source = df )
188+ source = df , ** kwargs )
269189 fig .toolbar .logo = None
270190 fig .axis .axis_label = None
271191 fig .axis .visible = False
@@ -281,8 +201,8 @@ def bokeh_piechart(df, x='value', y='counts', figure=None, radius=0.8, title='')
281201#fig = bokeh_piechart(df_test)
282202#show(fig)
283203
284-
285- def bokeh_corr_plot (df , x = 'x_values' , y = 'y_values' , figure = None , title = '' , markersize = 'markersize' , xlabel = 'Answers' , ylabel = 'Number of answers' , alpha = None ):
204+ @ preprocess_bokeh_input
205+ def bokeh_corr_plot (df , x = 'x_values' , y = 'y_values' , figure = None , title = '' , markersize = 'markersize' , xlabel = 'Answers' , ylabel = 'Number of answers' , alpha = None , ** kwargs ):
286206 """Plot an interactive circle with bokeh"""
287207
288208 if figure is None :
@@ -297,7 +217,7 @@ def bokeh_corr_plot(df, x='x_values', y='y_values', figure=None, title='', mark
297217 alpha = 1.0
298218 colors = ["#75968f" , "#a5bab7" , "#c9d9d3" , "#e2e2e2" , "#dfccce" , "#ddb7b1" , "#cc7878" , "#933b41" , "#550b1d" ]
299219 mapper = LinearColorMapper (palette = colors , low = df .data [y ].min (), high = df .data [y ].max ())
300- fig .circle (source = df , x = x , y = y , radius = 0.9 )#size=markersize, fill_color={'field': 'region', 'transform': color_mapper}, fill_alpha=alpha)
220+ fig .circle (source = df , x = x , y = y , radius = 0.9 , ** kwargs )#size=markersize, fill_color={'field': 'region', 'transform': color_mapper}, fill_alpha=alpha)
301221 #line_color='#7c7e71',
302222 #line_width=0.5,
303223 #line_alpha=0.5,
0 commit comments