1212This module contains functions to visualize data in an interactive way with mainly bokeh
1313"""
1414import numpy as np
15+ from functools import wraps
1516from collections import Counter
1617from bokeh .models import ColumnDataSource
1718from bokeh .plotting import figure as bokeh_figure
@@ -75,31 +76,53 @@ def add_legend_at(fig, position='right'):
7576 "width" : DEFAULT_FIGURE_WIDTH ,
7677 "height" : DEFAULT_FIGURE_HEIGHT }
7778}
79+ corr_theme = {
80+ "figure_kwargs" : {
81+ "x_range.range_padding" : 0.1 ,
82+ "xgrid.grid_line_color" : None ,
83+ "xaxis.major_label_orientation" : 1 ,
84+ "title.text_font_size" : '18px' ,
85+ "yaxis.axis_label_text_font_size" : '18px' ,
86+ "xaxis.axis_label_text_font_size" : '18px' ,
87+ "xaxis.major_label_text_font_size" : '16px' ,
88+ "yaxis.major_label_text_font_size" : '16px' ,
89+ "toolbar.logo" : None ,
90+ "toolbar_location" : "right" ,
91+ "legend.location" : "top_right" ,
92+ "legend.orientation" : "vertical" ,
93+ "legend.click_policy" : "hide" ,
94+ "width" : int (DEFAULT_FIGURE_WIDTH * 1.5 ),
95+ "height" : int (DEFAULT_FIGURE_HEIGHT * 1.5 )}
96+ }
97+
7898
7999
80- def apply_theme (func , theme = default_theme ):
100+
101+ def apply_theme (theme = default_theme ):
81102 """Decorator function to pre and post process a bokeh figure
82103
83104 :param func: the function to be decorated
84105 :type func: function
85106 """
86- def modified_plot (* args , ** kwargs ):
87- """Modifed plot functions"""
88-
89- # check if pandas data frame, if yes convert
90- # pack figure_kwargs
91- # set style?bokeh_barchart
92- # plot function kwargs
93-
94- # before adjustments
95- fig = func (* args , ** kwargs )
96- # after adjustments
97- figure_kwargs = theme .get ('figure_kwargs' , {})
98- for key , val in figure_kwargs .items ():
99- rek_set_attr (fig , key , val )
100- return fig
101-
102- return modified_plot
107+ def decorator (func ):
108+ @wraps (func )
109+ def modified_plot (* args , ** kwargs ):
110+ """Modifed plot functions"""
111+
112+ # check if pandas data frame, if yes convert
113+ # pack figure_kwargs
114+ # set style?bokeh_barchart
115+ # plot function kwargs
116+
117+ # before adjustments
118+ fig = func (* args , ** kwargs )
119+ # after adjustments
120+ figure_kwargs = theme .get ('figure_kwargs' , {})
121+ for key , val in figure_kwargs .items ():
122+ rek_set_attr (fig , key , val )
123+ return fig
124+ return modified_plot
125+ return decorator
103126
104127
105128def rek_set_attr (obj : object , key : str , val :object ) -> None :
@@ -125,7 +148,7 @@ def rek_set_attr(obj: object, key: str, val:object) -> None:
125148
126149
127150
128- @apply_theme
151+ @apply_theme ()
129152def bokeh_barchart (df , x = 'x_value' , y = ['y_value' ], factors = None , figure = None , data_visible = [True ], title = '' ,
130153 width = 0.1 , xlabel = '' , ylabel = 'Number of answers' , palette = Category20c ,
131154 fill_color = None , legend_labels = None , description = 'For more information about the HMC survey click here.' ,
@@ -227,7 +250,7 @@ def bokeh_barchart(df, x='x_value', y=['y_value'], factors=None, figure=None, da
227250 return fig
228251
229252# bokeh piechart
230- @apply_theme
253+ @apply_theme ()
231254def bokeh_piechart (df , x = 'x_value' , y = ['counts' ], figure = None , outer_radius = 0.7 , inner_radius = 0.4 ,
232255 title = '' , fill_color = None , legend_labels = None , line_color = 'black' , ** kwargs ):
233256 """Draw an interactive piechart with bokeh
@@ -328,7 +351,7 @@ def bokeh_piechart(df, x='x_value', y=['counts'], figure=None, outer_radius=0.7,
328351 toolbar_location = 'above' ,
329352 tools = tools ,
330353 tooltips = [('Data' , f'@{ x } ' ),
331- ('Percent ' , '@percent{0.00%}' ),
354+ ('Percentage ' , '@percent{0.00%}' ),
332355 ('Count' , f'@count' )])
333356 else :
334357 fig = figure
@@ -594,16 +617,19 @@ def bokeh_corr_plot(df, x='x_values', y='y_values', figure=None, title='', mark
594617
595618
596619
597- # @apply_theme
620+ @apply_theme ( theme = corr_theme )
598621def bokeh_corr_plot (source , x = 'x_values' , y = 'y_values' , figure = None , title = '' , x_range = None , y_range = None ,
599622 markersize = 'markersize' , xlabel = '' , ylabel = '' ,
600623 alpha = 0.6 , tooltips = None , leg_color = 'red' , nleg_items = 5 , ** kwargs ):
601624 """Plot an interactive circle with bokeh"""
602625
626+ #TODO: make this work with Multiple choice, i.e multiple x, y given
627+ #TODO: make this work with
628+
603629 default_tooltips = [(f"{ x } " , "@x" ),
604630 (f"{ y } " , "@y" ),
605- ("total " , "@total" ),
606- ("percentage " , "@percentage" )]
631+ ("Total " , "@total" ),
632+ ("Percentage " , "@percentage" )]
607633 if tooltips is None :
608634 tooltips = default_tooltips
609635
@@ -625,12 +651,12 @@ def bokeh_corr_plot(source, x='x_values', y='y_values', figure=None, title='',
625651 fig .outline_line_color = None
626652 fig .yaxis .axis_label = ylabel
627653 fig .xaxis .axis_label = xlabel
628- fig .title .text_font_size = '18px'
629- fig .yaxis .axis_label_text_font_size = '18px'
630- fig .xaxis .axis_label_text_font_size = '18px'
631- fig .xaxis .major_label_text_font_size = '16px'
632- fig .yaxis .major_label_text_font_size = '16px'
633- fig .toolbar .logo = None
654+ # fig.title.text_font_size='18px'
655+ # fig.yaxis.axis_label_text_font_size = '18px'
656+ # fig.xaxis.axis_label_text_font_size = '18px'
657+ # fig.xaxis.major_label_text_font_size = '16px'
658+ # fig.yaxis.major_label_text_font_size = '16px'
659+ # fig.toolbar.logo = None
634660
635661 # Or draw legend by hand as in, i.e a new plot/figure with no axis and text
636662 # https://docs.bokeh.org/en/latest/docs/gallery/burtin.html
@@ -699,12 +725,13 @@ def create_legend_items(number, size_min, color, fig, steps=None, data=None, sca
699725 leg_items .append (txt )
700726 return leg_items
701727
702- def create_legend_corr (fig , colors = ['red' , 'blue' , 'green' , 'red' , 'red' , 'red' ], width_ratio = 5 , scale_m = 1.0 ):
728+ def create_legend_corr (fig , colors = ['red' , 'blue' , 'green' , 'red' , 'red' , 'red' ],
729+ title = "Rel. amount\n of answers [%]" , width_ratio = 5 , scale_m = 1.0 ):
703730
704731 height = fig .height
705732 width = int (fig .width / width_ratio )
706733 fig2 = bokeh_figure (height = height , width = width ,
707- title = "Rel. amount \n of answers [%]" ,
734+ title = title ,
708735 toolbar_location = None ,
709736 tools = '' )
710737 leg_items = create_legend_items (5 , size_min = 0 , color = colors , fig = fig2 , scale_m = scale_m ) #[("circle", [circle])]
0 commit comments