def bokeh_heatmap(index=['Date', 'Representative']): #return three retention matrices percent_MRR, actual_MRR, contract_MRR = pivot_tables(combo=generate_data( n_sample=100, periods=30), index=index) #reformat data to column sparse matrix and place into dictionary x = [] y = [] vals = [] [(y.append(i[0]), x.append(i[1]), vals.append(v)) for i, v in np.ndenumerate(percent_MRR)] data = {'x': x, 'y': y, 'vals': vals} #heatmap instantiate hm = HeatMap(data=data, x='x', y='y', values='vals', stat=None, title='Revenue Retention by {}'.format(','.join(index)), ygrid=True, xgrid=True, xlabel='months', ylabel='contract start', yscale='categorical', palette=brewer['RdYlGn'][11], title_text_font_size='20pt') #add value labels to heat map # create formatted column of values for annotation labels data['labels'] = [ '{:.0%}'.format(round(i, 2)) if i >= 0 else '' for i in data['vals'] ] #dropping vals which are not json compliant del data['vals'] source = ColumnDataSource(data=data) labels = LabelSet(x='x', y='y', text='labels', level='glyph', x_offset=-2, y_offset=-4, source=source, render_mode='canvas', text_font_size='7pt', text_color='white') hm.add_layout(labels) # customize y-axis text # new_index=actual_MRR.sum(axis=1).reset_index() # new_index.rename(columns={0: 'Actual MRR'}, inplace=True) # new_index['Contract MRR']=contract_MRR.sum(axis=1).reset_index()[0] y_label_dict = {} for index, groups in enumerate(list(percent_MRR.index)): y_label_dict[index] = '-'.join(groups) #reverse y-axis order hm.y_range.start = max(y_label_dict.keys()) hm.y_range.end = min(y_label_dict.keys()) hm.x_range = Range1d(0, 12) #generate javascript code to reformat y-axis hm.yaxis.formatter = FuncTickFormatter(code="""var labels = {}; return labels[tick]; """.format(y_label_dict)) # fix ticks to display all values hm.yaxis[0].ticker = FixedTicker(ticks=list(y_label_dict.keys())) total_contract_mrr = contract_MRR.sum(axis=1) total_actual_mrr = actual_MRR.sum(axis=1) yaxis2_text = pd.concat([total_actual_mrr, total_contract_mrr], axis=1) yaxis2_text.reset_index(drop=True, inplace=True) yaxis2_text.columns = ['Actual MRR', 'Contract MRR'] yaxis2_text['text'] = yaxis2_text.apply( lambda row: '{:,.0f}/{:,.0f} \t ({:.0%})'.format( row['Actual MRR'], row['Contract MRR'], row['Actual MRR'] / row[ 'Contract MRR']), axis=1) yaxis2_text = yaxis2_text['text'].to_dict() #add right hand y-axis for additional information top = max(yaxis2_text.keys()) bottom = min(yaxis2_text.keys()) print(top, bottom) hm.extra_y_ranges = {'mrr': Range1d(top, bottom)} hm.add_layout(LinearAxis(y_range_name="mrr"), 'right') hm.yaxis[1].formatter = FuncTickFormatter(code="""var labels = {}; return labels[tick]; """.format(yaxis2_text)) hm.yaxis[1].ticker = FixedTicker(ticks=list(yaxis2_text.keys())) hm.yaxis[1].axis_label = 'Actual and Contract MRR' hm.yaxis[1].major_label_standoff = 30 # #help(hm.legend) # legend_items=list(hm.legend)[0].items # hm.legend.location = 'bottom_right' # exit() output_file('interactive.html') show(hm)
def process_file(self, file_path): """ Process the file given. This read from the file and add it to the codec. The codec will then decode the data and pass it to the UDP port. """ # Check if the file exist if os.path.exists(file_path): logger.info("Open file: " + file_path) # Open the file f = open(file_path, "rb") # Add the data from the file to the codec data = f.read(4096) while len(data) > 0: # Add data to codec self.codec.add(data) # Read next block from the file data = f.read(4096) # Close the file f.close() # Display the Heatmap and save it to HTML file output_file('test.html') hover = HoverTool(tooltips=[ ("index", "$index"), ("(x,y)", "($x, $y)"), ("desc", "@desc"), ]) TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom" hm = HeatMap( self.df_mag_ens, x='ens', y='bin', values='mag', stat=None, sort_dim={'x': False}, width=1000, spacing_ratio=0.9, tools=TOOLS, toolbar_location="above", # Move toolbar to top toolbar_sticky=False) # Make toolbar not to close to plot # Set min and max axis and invert axis xmin = self.df_mag_ens['ens'].min() xmax = self.df_mag_ens['ens'].max() ymax = self.df_mag_ens['bin'].min() # Swap Min and Max for y axis ymin = self.df_mag_ens['bin'].max() # Swap Min and Max for y axis hm.x_range = Range1d( xmin, xmax) # Set the min and max, so no gaps on edges hm.y_range = Range1d( ymin, ymax) # Set the min and max, so no gaps on edges show(hm) while True: input("Press enter to continue") break else: logger.error("File does not exist")