PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/pythalesians/graphics/graphs/lowleveladapters/adapterbokeh.py

https://gitlab.com/oytunistrator/pythalesians
Python | 199 lines | 117 code | 49 blank | 33 comment | 30 complexity | 004acec9d207354d33ab420c50cbb45e MD5 | raw file
  1. __author__ = 'saeedamen' # Saeed Amen / saeed@thalesians.com
  2. #
  3. # Copyright 2015 Thalesians Ltd. - http//www.thalesians.com / @thalesians
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
  6. # License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
  9. # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. #
  11. # See the License for the specific language governing permissions and limitations under the License.
  12. #
  13. """
  14. AdapterBokeh
  15. Wrapper for Bokeh to plot graph, with an easier to use common interface. Only provides very basic implementation of
  16. simple line charts currently, as a proof of concept.
  17. """
  18. from bokeh.plotting import figure, output_file, show
  19. import pandas
  20. from pythalesians.graphics.graphs.lowleveladapters.adaptertemplate import AdapterTemplate
  21. from pythalesians.graphics.graphs.graphproperties import GraphProperties
  22. from pythalesians.util.constants import Constants
  23. import numpy
  24. class AdapterBokeh(AdapterTemplate):
  25. def plot_2d_graph(self, data_frame, gp, chart_type):
  26. if gp is None: gp = GraphProperties()
  27. if gp.chart_type is None and chart_type is None: chart_type = 'line'
  28. scale_factor = gp.scale_factor / 2.0
  29. try:
  30. html = gp.html_file_output
  31. if (html is None):
  32. html = "bokeh.htm"
  33. output_file(html)
  34. except: pass
  35. bar_ind = numpy.arange(1, len(data_frame.index) + 1)
  36. xd, bar_ind, has_bar, no_of_bars = self.get_bar_indices(data_frame, gp, chart_type, bar_ind)
  37. if type(data_frame.index) == pandas.tslib.Timestamp:
  38. p1 = figure(
  39. x_axis_type = "datetime",
  40. plot_width = int(gp.width * scale_factor),
  41. plot_height = int(gp.height * scale_factor),
  42. x_range=(xd[0], xd[-1])
  43. )
  44. # if has a bar than categorical axis
  45. elif has_bar == True:
  46. p1 = figure(
  47. plot_width = int(gp.width * scale_factor),
  48. plot_height = int(gp.height * scale_factor),
  49. x_range=[str(x) for x in data_frame.index]
  50. )
  51. from math import pi
  52. p1.xaxis.major_label_orientation = pi/2
  53. # otherwise numerical axis
  54. else:
  55. p1 = figure(
  56. plot_width = int(gp.width * scale_factor),
  57. plot_height = int(gp.height * scale_factor),
  58. x_range=(xd[0], xd[-1])
  59. )
  60. # set the fonts
  61. p1.axis.major_label_text_font_size = str(10 * scale_factor) + "pt"
  62. p1.axis.major_label_text_font = Constants().bokeh_font
  63. p1.axis.major_label_text_font_style = Constants().bokeh_font_style
  64. p1.xaxis.axis_label_text_font_size = str(10 * scale_factor) + "pt"
  65. p1.xaxis.axis_label_text_font = Constants().bokeh_font
  66. p1.xaxis.axis_label_text_font_style = Constants().bokeh_font_style
  67. p1.xaxis.axis_label = gp.x_title
  68. p1.yaxis.axis_label_text_font_size = str(10 * scale_factor) + "pt"
  69. p1.yaxis.axis_label_text_font = Constants().bokeh_font
  70. p1.yaxis.axis_label_text_font_style = Constants().bokeh_font_style
  71. p1.yaxis.axis_label = gp.y_title
  72. p1.legend.label_text_font_size = str(10 * scale_factor) + "pt"
  73. p1.legend.label_text_font = Constants().bokeh_font
  74. p1.legend.label_text_font_style = Constants().bokeh_font_style
  75. p1.legend.fill_alpha = 0
  76. # set chart outline
  77. p1.outline_line_width = 0
  78. p1.title_text_font_size = str(14 * scale_factor) + "pt"
  79. p1.title_text_font = Constants().bokeh_font
  80. # TODO fix label
  81. # if gp.display_source_label:
  82. # p1.text([30 * scale_factor, 30 * scale_factor], [0, 0], text = [gp.brand_label],
  83. # text_font_size = str(10 * scale_factor) + "pt", text_align = "left",
  84. # text_font = Constants().bokeh_font)
  85. color_spec = self.create_color_list(gp, data_frame)
  86. import matplotlib
  87. bar_space = 0.2
  88. bar_width = (1 - bar_space) / (no_of_bars)
  89. bar_index = 0
  90. has_bar = False
  91. # plot each series in the dataframe separately
  92. for i in range(0, len(data_frame.columns)):
  93. label = str(data_frame.columns[i])
  94. glyph_name = 'glpyh' + str(i)
  95. # set chart type which can differ for each time series
  96. if chart_type is not None:
  97. if gp.chart_type is not None:
  98. if isinstance(gp.chart_type, list): chart_type = gp.chart_type[i]
  99. else: chart_type = gp.chart_type
  100. # get the color
  101. if color_spec[i] is None:
  102. color_spec[i] = self.get_color_list(i)
  103. try:
  104. color_spec[i] = matplotlib.colors.rgb2hex(color_spec[i])
  105. except: pass
  106. yd = data_frame.ix[:,i]
  107. # plot each time series as appropriate line, scatter etc.
  108. if chart_type == 'line':
  109. linewidth_t = self.get_linewidth(label,
  110. gp.linewidth, gp.linewidth_2, gp.linewidth_2_series)
  111. if linewidth_t is None: linewidth_t = 1
  112. if gp.display_legend:
  113. p1.line(xd, yd, color = color_spec[i], line_width=linewidth_t, name = glyph_name,
  114. legend = label,
  115. )
  116. else:
  117. p1.line(xd, data_frame.ix[:,i], color = color_spec[i], line_width=linewidth_t, name = glyph_name)
  118. elif(chart_type == 'bar'):
  119. bar_pos = [k - (1 - bar_space) / 2. + bar_index * bar_width for k in range(1,len(bar_ind) + 1)]
  120. bar_pos_right = [x + bar_width for x in bar_pos]
  121. if gp.display_legend:
  122. p1.quad(top=yd, bottom=0 * yd, left=bar_pos, right=bar_pos_right, color=color_spec[i], legend=label)
  123. else:
  124. p1.quad(top=yd, bottom=0 * yd, left=bar_pos, right=bar_pos_right, color=color_spec[i])
  125. bar_index = bar_index + 1
  126. bar_ind = bar_ind + bar_width
  127. elif chart_type == 'scatter':
  128. linewidth_t = self.get_linewidth(label,
  129. gp.linewidth, gp.linewidth_2, gp.linewidth_2_series)
  130. if linewidth_t is None: linewidth_t = 1
  131. if gp.display_legend:
  132. p1.circle(xd, yd, color = color_spec[i], line_width=linewidth_t, name = glyph_name,
  133. legend = label,
  134. )
  135. else:
  136. p1.circle(xd, yd, color = color_spec[i], line_width=linewidth_t, name = glyph_name)
  137. # set common properties
  138. # glyph = p1.select(name=glyph_name)[0].glyph
  139. try:
  140. p1.title = gp.title
  141. except: pass
  142. p1.grid.grid_line_alpha = 0.3
  143. show(p1) # open a browser
  144. def get_color_list(self, i):
  145. color_palette = Constants().bokeh_palette
  146. return color_palette[i % len(color_palette)]
  147. def generic_settings(self):
  148. return