def create_beta_diversity_tab(labels, plots_list): rank_to_img = {rank: [''] for rank in c.ALL_RANKS} for rank in c.ALL_RANKS: for label in labels: file = os.path.join("by_tool", label, 'beta_diversity_bc_' + rank) if file in plots_list: rank_to_img[rank][0] = rank_to_img[rank][ 0] + '<img src=' + '"' + file + '.png' + '"' + '/>' div_plots = Div(text=rank_to_img[c.SPECIES][0], css_classes=['bk-width-auto']) source = ColumnDataSource(data=rank_to_img) select2_rank_sample_callback = CustomJS(args=dict(source=source), code=""" div_plots.text = source.data[select2_rank.value][0]; """) select2_rank = Select(title="Taxonomic rank:", value=c.SPECIES, options=c.ALL_RANKS, css_classes=['bk-fit-content']) select2_rank.js_on_change('value', select2_rank_sample_callback) select2_rank_sample_callback.args["select2_rank"] = select2_rank select2_rank_sample_callback.args["div_plots"] = div_plots beta_div_column = column( select2_rank, div_plots, responsive=True, css_classes=['bk-width-auto', 'bk-width-auto-main']) return beta_div_column
def comnt_samp_selection(data_source=None, comnt_obj=None): """Return a select widget.""" code = """ //console.log('select: value=' + this.value, this.toString()) comnt_obj.value = this.value; var data = data_source.data; var selected_indices = []; var comnt_value; for (var i = 0; i < data.COMNT_SAMP.length; i++) { comnt_value = data.COMNT_SAMP[i]; if (comnt_value == this.value) { selected_indices.push(i); } } data_source.selected.indices = selected_indices; """ callback = CustomJS(code=code, args={ 'data_source': data_source, 'comnt_obj': comnt_obj }) select = Select( title="Select comnt incl. index", value='None', options=[], ) select.js_on_change("value", callback) return select
def getTimeSeries_newish(df_tws): df_tws['date'] = pd.to_datetime(df_tws['date'], format='%m/%d/%Y') grouped = df_tws.groupby( [pd.Grouper(key='date', freq='M'), 'keyword'])['sentiment'].count().to_frame(name='count').reset_index() print(grouped) source = ColumnDataSource(grouped) p = figure(plot_height=400, x_axis_type='datetime') p.line(x='date', y='count', line_width=2, source=source, legend='Music') p.line(x='date', y='count', line_width=2, source=source, legend='Art') p.yaxis.axis_label = 'Number of Tweets' s = Select(title="test", value="music", options=['art', 'music']) w2 = CheckboxGroup(labels=["One", "Two", "Three"], active=[1, 1, 1]) callback = CustomJS(args=dict(src=source), code=''' src.change.emit(); ''') js_filter = CustomJSFilter(code=''' var indices = []; for (var i = 0; i < src.get_length(); i++){ if (src.data['keyword'][i] == select.value){ indices.push(true); } else { indices.push(false); } } return indices; ''') s.js_on_change('value', callback) return p, s, w2
def create(): columns = [ TableColumn(field="name", title="File name"), TableColumn(field="datetime", title="Datetime"), TableColumn(field="driver", title="Driver"), TableColumn(field="track", title="Track"), TableColumn(field="car", title="Car"), TableColumn(field="lap", title="Lap"), TableColumn(field="time", title="Lap time"), ] source = ColumnDataSource() filter_source = ColumnDataSource() data_table = DataTable(source=filter_source, columns=columns, width=800) ### https://gist.github.com/dennisobrien/450d7da20daaba6d39d0 # callback code to be used by all the filter widgets combined_callback_code = """ var data = {}; var original_data = source.data; var track = track_select_obj.value; var car = car_select_obj.value; for (var key in original_data) { data[key] = []; for (var i = 0; i < original_data['track'].length; ++i) { if ((track === "ALL" || original_data['track'][i] === track) && (car === "ALL" || original_data['car'][i] === car)) { data[key].push(original_data[key][i]); } } } filter_source.data = data; filter_source.change.emit(); target_obj.change.emit(); """ # define the filter widgets track_select = Select(title="Track:", value='ALL', options=['ALL']) car_select = Select(title="Car:", value='ALL', options=['ALL']) # define the callback object generic_callback = CustomJS(args=dict(source=source, filter_source=filter_source, track_select_obj=track_select, car_select_obj=car_select, target_obj=data_table), code=combined_callback_code) # connect the callbacks to the filter widgets track_select.js_on_change('value', generic_callback) car_select.js_on_change('value', generic_callback) filters = row(track_select, car_select) ###### return filters, data_table, source, filter_source, track_select, car_select
def mg_select(csvList, bar_source, status): select = Select(title="csv File:", value=csvList[0], options=[*enumerate(csvList)]) # Select Code with open(dir_path + '/select.js', 'r') as select_file: select_code = select_file.read() select_callback = CustomJS(args=dict(select=select, bar_source=bar_source, status=status), code=select_code) select.js_on_change('value', select_callback) return select
from bokeh.models.widgets import Select from bokeh.core.enums import SizingMode N = 4000 x = np.random.random(size=N) * 100 y = np.random.random(size=N) * 100 radii = np.random.random(size=N) * 1.5 colors = [ "#%02x%02x%02x" % (int(r), int(g), 150) for r, g in zip(50+2*x, 30+2*y) ] TOOLS="hover,crosshair,pan,wheel_zoom,zoom_in,zoom_out,box_zoom,undo,redo,reset,tap,save,box_select,poly_select,lasso_select" sizing_mode = "fixed" select = Select(title="Sizing mode", value=sizing_mode, options=list(SizingMode)) plot = figure(tools=TOOLS) plot.scatter(x, y, radius=radii, fill_color=colors, fill_alpha=0.6, line_color=None) layout = column(select, plot, sizing_mode=sizing_mode) select.js_on_change('value', CustomJS(args=dict(layout=layout, plot=plot), code=""" var sizing_mode = this.value; layout.sizing_mode = sizing_mode; plot.sizing_mode = sizing_mode; """)) output_file("sizing_mode.html", title="sizing_mode.py example") show(layout)
def bokeh_spacetimepop( frm, geometry, title = '', preamble = '', varNames = None, varNotes = dict(), pw = 700, ph = 700, xZones = dict(), ): import numpy as np import pandas as pd df = pd.DataFrame idx = pd.IndexSlice import geopandas as gpd gdf = gpd.GeoDataFrame from bokeh.models import ColumnDataSource, HoverTool, Legend, LegendItem, CDSView, IndexFilter from bokeh.plotting import figure, show from bokeh.io import output_notebook # frm = frm.reset_index().pivot(index = frm.index.names[0], columns = frm.index.names[1]) frm = frm.copy() frm = frm.sort_index() # geometry = geometry.copy() from bokeh.models import Div title = f'<h1>{title}</h1>' title = Div( text = title, width = pw, ) preamble = Div( text = preamble, width = pw, ) if varNames is None: varNames = frm.columns.sort_values() varMetaName = varNames.name else: varMetaName = 'variable' varNames = list(varNames) seriesNames = frm.index.levels[1].sort_values() seriesMetaName = seriesNames.name seriesNames = list(seriesNames) dates = [str(int(round(i.to_numpy().astype(int) / 1e6))) for i in frm.index.levels[0]] frm.index = frm.index.set_levels(dates, level = 0) defaultVar = varNames[0] defaultDate = dates[-1] pivotFrm = frm.reset_index() \ .pivot(index = frm.index.names[0], columns = frm.index.names[1]) \ .sort_index() defaultVar = varNames[0] defaultDate = dates[-1] for key in varNames: if not key in varNotes: varNotes[key] = '' else: varNotes[key] = f'<i>{varNotes[key]}</i>' varNote = Div( text = varNotes[defaultVar], width = pw - 120, ) lineSources = { key: ColumnDataSource(pivotFrm[key]) for key in pivotFrm.columns.levels[0] } lineSource = ColumnDataSource(pivotFrm[defaultVar]) lineSource.name = defaultVar barSources = dict() for varName in varNames: for index, date in zip(sorted(pivotFrm.index), dates): series = pivotFrm.loc[index, varName] subFrm = df(dict( name = series.index, value = series.values, height = abs(series.values), offset = series.values / 2. )) barSources[varName + '_' + date] = ColumnDataSource(subFrm) barSource = ColumnDataSource(barSources[defaultVar + '_' + defaultDate].data) barSource.name = ', '.join([str(defaultVar), str(defaultDate)]) bounds = geometry.bounds minx = np.min(bounds['minx']) maxx = np.max(bounds['maxx']) miny = np.min(bounds['miny']) maxy = np.max(bounds['maxy']) aspect = (maxx - minx) / (maxy - miny) from shapely.geometry import Polygon import itertools corners = list(itertools.product(geometry.total_bounds[::2], geometry.total_bounds[1::2])) allPoly = Polygon([corners[0], corners[1], corners[3], corners[2]]) allPoly = allPoly.centroid.buffer(np.sqrt(allPoly.area) / 1e6) for name in frm.index.levels[1]: if not name in geometry.index: geometry[name] = allPoly geometry = geometry.simplify(np.sqrt(geometry.area).min() * 10. ** 3.5) geoFrm = frm.reset_index().pivot(index = frm.index.names[1], columns = frm.index.names[0]) geoFrm.columns = geoFrm.columns.map('_'.join).str.strip('_') geoFrm['geometry'] = geometry geoFrm = gdf(geoFrm) from bokeh.models import GeoJSONDataSource geoJSON = geoFrm.reset_index().to_json() geoSource = GeoJSONDataSource(geojson = geoJSON) mins = {n: frm[n].min() for n in varNames} maxs = {n: frm[n].max() for n in varNames} xName = frm.index.names[0] lineFig = figure( x_axis_type = 'datetime', y_range = (mins[defaultVar], maxs[defaultVar]), plot_height = int((ph - 100) * 1. / 3.), plot_width = pw, toolbar_location = 'left', tools = 'save, xpan, box_zoom, reset, xwheel_zoom', active_scroll = 'auto', # title = title, ) barFig = figure( x_range = seriesNames, plot_height = int((ph - 100) * 1. / 2.), plot_width = pw, # title = "Scores on my birthday", toolbar_location = None, tools = "" ) barFig.xgrid.grid_line_color = None barFig.xaxis.major_label_orientation = 'vertical' mapFig = figure( plot_width = pw - 20, plot_height = int(round((pw - 20) / aspect)), toolbar_location = 'right', tools = 'pan, wheel_zoom, reset', background_fill_color = "lightgrey" ) mapFig.xgrid.grid_line_color = None mapFig.ygrid.grid_line_color = None from matplotlib.pyplot import get_cmap from matplotlib.colors import rgb2hex cmap = get_cmap('nipy_spectral') cs = [rgb2hex(cmap(i / len(seriesNames), alpha = 0.5)) for i in range(len(seriesNames))] lines = [] for seriesName, colour in zip(seriesNames, cs): line = lineFig.line( xName, seriesName, source = lineSource, color = colour, alpha = 0.8, muted_color = 'gray', muted_alpha = 0.3, muted = True, line_width = 2, # legend_label = seriesName, ) from bokeh.models import HoverTool lineFig.add_tools(HoverTool( renderers = [ line, ], tooltips = [ (seriesMetaName.capitalize(), seriesName), (xName.capitalize(), f'@{xName}' + '{%Y-%m-%d}'), ('Value', f'@{{{seriesName}}}'), ], formatters = { f'@{xName}': 'datetime', seriesName: 'numeral', }, toggleable = False )) lines.append(line) bars = [] for i, (seriesName, colour) in enumerate(zip(seriesNames, cs)): view = CDSView(source = barSource, filters = [IndexFilter([i,]),]) bar = barFig.rect( source = barSource, view = view, x = 'name', y = 'offset', height = 'height', width = 0.9, color = colour, muted_color = 'gray', muted_alpha = 0.3, muted = True, ) bars.append(bar) from bokeh.palettes import Viridis256 from bokeh.models import LinearColorMapper, ColorBar palette = Viridis256 mapColourMapper = LinearColorMapper( palette = palette, low = frm.loc[idx[defaultDate, :], defaultVar].min(), high = frm.loc[idx[defaultDate, :], defaultVar].max(), ) mapColourBar = ColorBar( color_mapper = mapColourMapper, label_standoff = 8, width = 30, height = int(round(mapFig.plot_height * 0.9)), border_line_color = None, location = (0, 0), orientation = 'vertical', ) mapFig.add_layout(mapColourBar, 'left') patches = [] for i, seriesName in enumerate(seriesNames): view = CDSView(source = geoSource, filters = [IndexFilter([i,]),]) patch = mapFig.patches( 'xs', 'ys', source = geoSource, view = view, fill_color = dict( field = '_'.join([defaultVar, defaultDate]), transform = mapColourMapper, ), line_color = 'grey', line_width = 0.25, fill_alpha = 0., name = '_'.join([defaultVar, defaultDate]) ) patches.append(patch) from bokeh.models import HoverTool mapHover = HoverTool( renderers = patches, tooltips = [ (seriesMetaName.capitalize(), f'@{seriesMetaName}'), ('Value', '@$name'), ] ) mapFig.add_tools(mapHover) from bokeh.models import BoxAnnotation from bokeh.models import Label for name, zone in xZones.items(): convD = lambda x: int(round(pd.Timestamp(x).to_numpy().astype(int) / 1e6)) left, right = [None if val is None else convD(val) for val in zone] zone = BoxAnnotation( left = left, right = right, fill_alpha = 0.1, fill_color = 'gray', ) zoneLabel = Label( text = name + ' (end)' if left is None else name, text_font_size = '8pt', x = right if left is None else left, y = 10, x_units = 'data', y_units = 'screen', angle = -90 if left is None else 90, angle_units = 'deg', x_offset = -10 if left is None else 10, y_offset = 5 * (len(name) + 6) if left is None else 0 ) lineFig.add_layout(zone) lineFig.add_layout(zoneLabel) from bokeh.models import Span span = Span( location = int(defaultDate), dimension = 'height', line_color = 'red', # line_dash = 'dashed', line_width = 1 ) lineFig.add_layout(span) from bokeh.models.widgets import DateSlider slider = DateSlider( title = 'Date', start = int(dates[0]), end = int(dates[-1]), step = int(8.64 * 1e7), # days value = int(defaultDate), width = pw - 60, align = 'end' ) from bokeh.models.widgets import Select select = Select( title = "Choose data:", options = varNames, value = defaultVar, width = 100, ) from bokeh.models import CheckboxGroup checkboxes = CheckboxGroup( labels = seriesNames, active = [], ) checkboxAll = CheckboxGroup( labels = ['All',], active = [], ) from bokeh.models import CustomJS callback = CustomJS( args = dict( y_range = lineFig.y_range, lineSources = lineSources, lineSource = lineSource, barSources = barSources, barSource = barSource, bars = bars, lines = lines, patches = patches, select = select, slider = slider, span = span, checkboxes = checkboxes, varNote = varNote, varNotes = varNotes, geoSource = geoSource, mapColourMapper = mapColourMapper, mins = mins, maxs = maxs, ), code = """ lineSource.data = lineSources[select.value].data lineSource.name = select.value lineSource.change.emit() span.location = slider.value span.change.emit() y_range.setv({'start': mins[select.value], 'end': maxs[select.value]}) varNote.text = varNotes[select.value] varNote.change.emit() const barChoice = select.value + '_' + slider.value barSource.data = barSources[barChoice].data barSource.name = select.value.toString() + ', ' + slider.value.toString() barSource.change.emit() for (let i = 0; i < lines.length; i++){ let checked = checkboxes.active.includes(i) lines[i].muted = !(checked) bars[i].muted = !(checked) var alpha = checked ? 1 : 0; patches[i].glyph.fill_alpha = alpha } const newCol = select.value + '_' + slider.value for (let i = 0; i < lines.length; i++){ patches[i].glyph.fill_color['field'] = newCol patches[i].name = newCol } mapColourMapper.low = mins[select.value] mapColourMapper.high = maxs[select.value] geoSource.change.emit() """, ) allCheckCallback = CustomJS( args = dict( lines = lines, checkboxes = checkboxes, checkboxAll = checkboxAll, callback = callback ), code = """ checkboxes.active.length = 0 if (checkboxAll.active.length > 0) { let arr = [] for (let i = 0; i < lines.length; i++){ arr.push(i) } checkboxes.active.push(...arr) } checkboxes.change.emit() callback.execute() """ ) slider.js_on_change('value', callback) select.js_on_change('value', callback) checkboxes.js_on_change('active', callback) checkboxAll.js_on_change('active', allCheckCallback) from bokeh.layouts import column, row layout = column( title, preamble, row(select, varNote), row(column(lineFig, slider, barFig), column(checkboxes, checkboxAll)), mapFig ) return layout
def client1(request): if request.user.is_authenticated(): username = request.user.get_username() if request.method == 'GET' and request.user.is_authenticated(): user_profile = UserProfile.objects.get(user=request.user) is_supervisor = user_profile.supervisor #x= [1,2,3,4,5,6,7] x = [ "20-Oct-17", "27-Oct-17", "02-Nov-17", "09-Nov-17", "16-Nov-17", "23-Nov-17", "30-Nov-17" ] y = [2500, 2250, 2300, 2150, 2050, 2100, 2200] title = 'Weight and Calories over Time' extra_y = [85, 83, 80, 78, 77, 76, 75] hover = HoverTool(tooltips=[("calories", "@y kcal"), ("date", "@x")], names=["calories"]) plot = figure(title=title, x_range=x, y_range=Range1d(2000, 2500), x_axis_label='Time (Weekly)', y_axis_label='Daily Average Calores (kcal)', plot_width=600, plot_height=400, tools=[hover]) plot.line(x, y, legend='Calories Over Time', line_width=2, name="calories") plot.circle(x, y, fill_color="blue", size=8, legend='Calories Over Time') plot.extra_y_ranges['weight'] = Range1d(70, 90) hoverweight = HoverTool(tooltips=[("weight", "@y kg"), ("date", "@x")], names=["weight"]) #plot.multi_line([x, y], [x, extra_y], color=["firebrick", "navy"], line_width=4) plot.add_layout( LinearAxis(y_range_name="weight", axis_label="Weight (kg)"), 'right') source = ColumnDataSource(data=dict(x=x, y=extra_y)) plot.circle('x', 'y', source=source, fill_color="firebrick", line_color="firebrick", size=8, y_range_name="weight", name="weight", legend="Weight Over Time") plot.line(x, extra_y, legend='Weight Over Time', line_width=2, y_range_name="weight", name="weight", color="firebrick") zoom = WheelZoomTool() plot.add_tools(hoverweight, PanTool(), zoom) plot.legend.location = "bottom_left" plot.legend.click_policy = "hide" plot.toolbar.active_scroll = zoom plot.toolbar.logo = None plot.toolbar_location = None #Store components script, div = components(plot) #The code which changes kilos to pounds. This needs to be integrated using ajax I think. callback = CustomJS(args=dict(source=source), code=""" var data = source.data; var f = cb_obj.value y = data['y'] if (f === "Kilos") { for (i = 0; i < y.length; i++) { y[i] = y[i] / 2.2 } } if (f === "Pounds") { for (i = 0; i < y.length; i++) { y[i] = y[i] * 2.2 } } source.change.emit(); """) s = Select(title='Units', value="Kilos", options=['Kilos', 'Pounds']) s.js_on_change('value', callback) select_script, select_div = components(s) #pie chart# # a color for each pie piece colors = ["red", "blue"] p = figure(x_range=(-1, 1), y_range=(-1, 1), plot_width=200, plot_height=200, tools=[]) p.wedge(x=0, y=0, radius=1, start_angle=0, end_angle=0.12, color="red", legend="weight loss", name="change") p.wedge(x=0, y=0, radius=1, start_angle=0.12, end_angle=0, color="blue", legend="current weight", name="current") hoverchange = HoverTool(tooltips=[ ("Total Weight Loss", "10kg (12%)"), ], names=["change"]) hovercurrent = HoverTool(tooltips=[ ("Current Weight", "75kg (88%)"), ], names=["current"]) p.add_tools(hoverchange, hovercurrent, PanTool(), zoom) # display/save everythin script1, div1 = components(p) #Feed them to the Django template. return render( request, 'visualisation/client1.html', { 'username': str(username), 'is_supervisor': is_supervisor, 'script': script, 'div': div, 'script1': script1, 'div1': div1, 'select_script': select_script, 'select_div': select_div })
plot_height = 600 dw = 10 dh = 10 N = 651 select = Select(title='Select Year/Date', options=path, value=path[0]) callback = CustomJS(args=dict(source=source), code=""" var data = source.data; var s = cb_obj.value x=data['infared_'+s] data['infared'] = x source.change.emit() """) select.js_on_change('value', callback) p = figure(title='Infared outliers', plot_width=plot_width, plot_height=plot_height, x_range=(0, dw), y_range=(0, dh)) pg = p.image(image='infared', x=0, y=0, dw=dw, dh=dh, source=source, palette='Spectral11') show(row(p, select))
n_smooth_name = Div(text= " Repeats of Smoothing:", width= 150, height=30 ) # bin_name = Div(text= " Bin Every:", width= 150, height=30 ) int_name = Div(text= " Intensity Threshold (%)", width= 150, height=30 ) sub_name = Select(options=['Substract Minimum', 'Substract Line', 'Substract Curved'], name='sub_mode', value='Substract Minimum', width= 150, height=30 ) # add_name = Div(text= " Adduct Mass (Da)", width= 150, height=30 ) # dat_name = Div(text= " Data Reduction (%)", width= 150, height=30 ) #pro_name = Div(text= " bla", width= 150, height=30 ) dt_name = Div(text= " <h2>Data Processing</h2>", height=45 ) dtp_update=CustomJS(args=dict(DataProcessingParameters=DataProcessingParameters), code=open(os.path.join(os.getcwd(), 'JS_Functions', "DataProcessingParameters_update_cb.js")).read()) cropping_slider.js_on_change('value', dtp_update) n_smooth.js_on_change('value', dtp_update) gaussian_smooth.js_on_change('value', dtp_update) intensity_threshold.js_on_change('value', dtp_update) substract.js_on_change('value', dtp_update) sub_name.js_on_change('value', dtp_update) processing_cb=CustomJS(args=dict(peak_mz=peak_mz, bg_mz=bg_mz, raw_mz=raw_mz, proc_mz=proc_mz, DataProcessingParameters=DataProcessingParameters, series_data=series_data, series_sele=series_sele, series_names=series_names, series_mz=series_mz), code=open(os.path.join(os.getcwd(), 'JS_Functions', "navia_functions.js")).read() + open(os.path.join(os.getcwd(), 'JS_Functions', "data_processing_cb.js")).read()) process_data=Button(label='Process Data', width=100, height=30, button_type='success', callback=processing_cb) reset_cb=CustomJS(args=dict(process_data=process_data, peak_mz=peak_mz, bg_mz=bg_mz, raw_mz=raw_mz, proc_mz=proc_mz, series_data=series_data, series_sele=series_sele, series_names=series_names, series_mz=series_mz), code=open(os.path.join(os.getcwd(), 'JS_Functions', "navia_functions.js")).read() + open(os.path.join(os.getcwd(), 'JS_Functions', "reset_cb.js")).read()) reset_data=Button(label='Reset Processing', width=80, height=30, button_type='danger', callback=reset_cb) dt_names = Column(cropping, gau_name, n_smooth_name ,int_name, sub_name, reset_data)#, pro_name) dt_inp=Column(cropping_slider, gaussian_smooth, n_smooth, intensity_threshold, substract, process_data) grid_text = Div(text= " Show Grid", width= 150, height=30 ) grid_sele = Toggle(label='on', active=True, width=100, height=30, callback=toggle_cb) for x_grid_line in plot_canvas.xgrid: grid_sele.js_link('active', x_grid_line, 'visible') for y_grid_line in plot_canvas.ygrid:
def bokeh_plot(import_df): import pandas as pd import numpy as np from bokeh.plotting import figure, show from bokeh.layouts import layout, widgetbox, row, column, gridplot from bokeh.models import ColumnDataSource, HoverTool, BoxZoomTool, ResetTool, PanTool, CustomJS, PrintfTickFormatter, WheelZoomTool, SaveTool, LassoSelectTool, NumeralTickFormatter from bokeh.models.widgets import Slider, Select, TextInput, Div, Tabs, Panel, DataTable, DateFormatter, TableColumn, PreText, NumberFormatter, RangeSlider from bokeh.io import curdoc from functools import lru_cache from bokeh.transform import dodge from os.path import dirname, join from bokeh.core.properties import value #load plotting data here @lru_cache() def load_data(): df = import_df df.dropna(how='all', axis=0) #Northest=['3229','3277','3276','3230','3259','All_Stores_NE'] df.location_reference_id = df.location_reference_id.astype(str) #df['region'] = ['Northeast' if x in Northest else 'Midwest' for x in df['location_reference_id']] df['date'] = pd.to_datetime(df['date']) df[[ 'BOH_gt_Shelf_Capacity', 'OTL_gt_Shelf_Capacity', 'Ideal_BOH_gt_Shelf_Capacity', 'BOH_lt_Ideal', 'BOH_eq_Ideal', 'BOH_gt_Ideal', 'Demand_Fulfilled', 'Fill_Rate', 'Backroom_OH', 'Total_OH', 'Prop_OH_in_Backroom', 'Never_Q98_gt_POG', 'Never_Ideal_BOH_gt_POG', 'Sometimes_OTL_Casepack_1_gt_POG', 'Always_OTL_Casepack_1_le_POG', 'Non_POG' ]] = df[[ 'BOH > Shelf Capacity', 'OTL > Shelf Capacity', 'Ideal BOH > Shelf Capacity', 'BOH < Ideal', 'BOH = Ideal', 'BOH > Ideal', 'Demand Fulfilled', 'Fill Rate', 'Backroom_OH', 'Total OH', 'Prop OH in Backroom', 'Never: Q98 > POG', 'Never: Ideal BOH > POG', 'Sometimes: OTL+Casepack-1 > POG', 'Always: OTL+Casepack-1 <= POG', 'Non-POG' ]] df['date_bar'] = df['date'] df['date_bar'] = df['date_bar'].astype(str) return df #Filter data source for "All" stores OR data agrregation on DC level df_agg = load_data().groupby(['location_reference_id'], as_index=False).sum() source1 = ColumnDataSource(data=df_agg) sdate = min(load_data()['date']) edate = max(load_data()['date']) nodes = len(list(load_data().location_reference_id.unique())) days = len(list(load_data().date.unique())) policy = "Prod" #list of dates for vbar charts x_range_list = list(load_data().date_bar.unique()) #direct access to number of location_reference_idand region all_locations1 = list(load_data().location_reference_id.unique()) #agg_value=['All'] #all location_reference_idfrom csv file along with an option for agg data "All" #all_locations=all_locations1+agg_value #all_regions = ['Northeast', 'Midwest'] all_regions = list(load_data().region.unique()) desc = Div(text="All locations", width=230) pre = Div(text="_", width=230) location = Select(title="Location", options=all_locations1, value="All_Stores_NE") region = Select(title="Region", options=all_regions, value="NE") text_input = TextInput(value="default", title="Search Location:") #full data set from load_data(df=df_import) source = ColumnDataSource(data=load_data()) original_source = ColumnDataSource(data=load_data()) #plotting starts........... here are total 8 graphs for each Metric. #Back room on hand hover = HoverTool( tooltips=[("Location", "@location_reference_id"), ( "Date", "@date_bar"), ("Backroom_OH", "@Backroom_OH{0,0.00}")]) TOOLS = [ hover, BoxZoomTool(), LassoSelectTool(), WheelZoomTool(), PanTool(), ResetTool(), SaveTool() ] p = figure(x_range=x_range_list, plot_width=1000, plot_height=525, title="Backroom On hand by store", tools=TOOLS, toolbar_location='above', x_axis_label="Date", y_axis_label="Backroom OH") p.background_fill_color = "#e6e9ed" p.background_fill_alpha = 0.5 p.vbar(x=dodge('date_bar', -0.25, range=p.x_range), top='Backroom_OH', hover_alpha=0.5, hover_line_color='black', width=0.8, source=source, color="#718dbf") p.xaxis.major_label_orientation = 1 p.legend.border_line_width = 3 p.legend.border_line_color = None p.legend.border_line_alpha = 0.5 p.title.text_color = "olive" #inbound outbound hover_m = HoverTool( tooltips=[("Location", "@location_reference_id"), ( "Date", "@date_bar"), ( "Inbound", "@Inbound{0,0.00}"), ("Outbound", "@Outbound{0,0.00}")]) TOOLS_m = [ hover_m, BoxZoomTool(), LassoSelectTool(), WheelZoomTool(), PanTool(), ResetTool(), SaveTool() ] m = figure(plot_height=525, plot_width=1000, x_range=x_range_list, title="Inbound/Outbound by store", tools=TOOLS_m, toolbar_location='above', x_axis_label="Date", y_axis_label="Units") m.background_fill_color = "#e6e9ed" m.background_fill_alpha = 0.5 m.vbar(x=dodge('date_bar', -0.25, range=m.x_range), top='Inbound', hover_alpha=0.5, hover_line_color='black', width=0.4, source=source, color="#718dbf", legend=value("Inbound")) m.vbar(x=dodge('date_bar', 0.25, range=m.x_range), top='Outbound', hover_alpha=0.5, hover_line_color='black', width=0.4, source=source, color="#e84d60", legend=value("Outbound")) m.xaxis.major_label_orientation = 1 m.legend.border_line_width = 3 m.legend.border_line_color = None m.legend.border_line_alpha = 0.5 m.title.text_color = "olive" #Stockout hover_s = HoverTool( tooltips=[("Location", "@location_reference_id"), ( "Date", "@date_bar"), ( "BOH_OOS", "@BOH_OOS{0,0.000}"), ("EOH_OOS", "@EOH_OOS{0,0.000}")]) TOOLS_s = [ hover_s, BoxZoomTool(), LassoSelectTool(), WheelZoomTool(), PanTool(), ResetTool(), SaveTool() ] s = figure(plot_height=525, plot_width=1000, title="Stockouts by store", x_axis_type="datetime", toolbar_location='above', tools=TOOLS_s, x_axis_label="Date", y_axis_label="Prop Stockout") s.background_fill_color = "#e6e9ed" s.background_fill_alpha = 0.5 s.circle(x='date', y='EOH_OOS', source=source, fill_color=None, line_color="#4375c6") s.line(x='date', y='EOH_OOS', source=source, hover_alpha=0.5, hover_line_color='black', line_width=2, line_color='navy', legend=value("EOH OOS")) s.circle(x='date', y='BOH_OOS', source=source, fill_color=None, line_color="#4375c6") s.line(x='date', y='BOH_OOS', source=source, hover_alpha=0.5, hover_line_color='black', line_width=2, line_color='red', legend=value("BOH OOS")) s.legend.border_line_width = 3 s.legend.border_line_color = None s.legend.border_line_alpha = 0.5 s.title.text_color = "olive" #Fill rate hover_t = HoverTool( tooltips=[("Location", "@location_reference_id"), ( "Date", "@date_bar"), ("Fill Rate", "@Fill_Rate{0,0.00}")]) TOOLS_t = [ hover_t, BoxZoomTool(), LassoSelectTool(), WheelZoomTool(), PanTool(), ResetTool(), SaveTool() ] t = figure(plot_height=525, x_range=x_range_list, plot_width=1000, title="Fill rates by store", tools=TOOLS_t, toolbar_location='above', x_axis_label="Date", y_axis_label="Fill rate") t.background_fill_color = "#e6e9ed" t.background_fill_alpha = 0.5 t.vbar(x=dodge('date_bar', -0.25, range=t.x_range), top='Fill Rate', hover_alpha=0.5, hover_line_color='black', width=0.8, source=source, color="#718dbf") t.xaxis.major_label_orientation = 1 t.legend.border_line_width = 3 t.legend.border_line_color = None t.legend.border_line_alpha = 0.5 t.title.text_color = "olive" # % Backroom spillover hover_w = HoverTool( tooltips=[("Location", "@location_reference_id"), ("Date", "@date_bar"), ("Prop OH in Backroom", "@Prop_OH_in_Backroom{0,0.00}")]) TOOLS_w = [ hover_w, BoxZoomTool(), LassoSelectTool(), WheelZoomTool(), PanTool(), ResetTool(), SaveTool() ] w = figure(plot_height=525, plot_width=1000, title="Prop OH in Backroom by store", x_axis_type="datetime", tools=TOOLS_w, toolbar_location='above', x_axis_label="Date", y_axis_label=" % Backroom spillover") w.background_fill_color = "#e6e9ed" w.background_fill_alpha = 0.5 w.circle(x='date', y='Prop OH in Backroom', source=source, fill_color=None, line_color="#4375c6") w.line(x='date', y='Prop OH in Backroom', source=source, hover_alpha=0.5, hover_line_color='black', line_width=2, line_color='navy') w.title.text_font_style = "bold" w.title.text_color = "olive" w.legend.click_policy = "hide" w.yaxis[0].formatter = NumeralTickFormatter(format="0.0%") #BOH vs Ideal hover_f = HoverTool( tooltips=[("Location", "@location_reference_id"), ( "Date", "@date_bar"), ('BOH < Ideal', "@BOH_lt_Ideal{0,0.00}" ), ('BOH > Ideal', "@BOH_gt_Ideal{0,0.00}" ), ('BOH = Ideal', "@BOH_eq_Ideal{0,0.00}")]) TOOLS_f = [ hover_f, BoxZoomTool(), LassoSelectTool(), WheelZoomTool(), PanTool(), ResetTool(), SaveTool() ] colors = ["#c9d9d3", "#718dbf", "#e84d60"] BOH_vs_ideal = ['BOH < Ideal', 'BOH > Ideal', 'BOH = Ideal'] f = figure(x_range=x_range_list, plot_height=525, plot_width=1000, title="BOH vs Ideal by store", toolbar_location='above', x_axis_label="Date", y_axis_label="Prop", tools=TOOLS_f) f.vbar_stack(BOH_vs_ideal, x='date_bar', width=0.9, color=colors, source=source, legend=[value(x) for x in BOH_vs_ideal], name=BOH_vs_ideal) f.xaxis.major_label_orientation = 1 f.legend.border_line_width = 3 f.legend.border_line_color = None f.legend.border_line_alpha = 0.5 f.title.text_color = "olive" #Pog Fit hover_g = HoverTool( tooltips=[("Location", "@location_reference_id"), ( "Date", "@date_bar"), ('Never: Q98 > POG', "@Never_Q98_gt_POG{0,0.00}"), ("Never: Ideal BOH > POG", "@Never_Ideal_BOH_gt_POG{0,0.00}"), ("Sometimes: OTL+Casepack-1 > POG", "@Sometimes_OTL_Casepack_1_gt_POG{0,0.00}"), ("Always: OTL+Casepack-1 <= POG", "@Always_OTL_Casepack_1_le_POG{0,0.00}" ), ("Non-POG'", "@Non_POG{0,0.00}")]) TOOLS_g = [ hover_g, BoxZoomTool(), LassoSelectTool(), WheelZoomTool(), PanTool(), ResetTool(), SaveTool() ] colors2 = ['#79D151', "#718dbf", '#29788E', '#fc8d59', '#d53e4f'] pog_fit = [ 'Never: Q98 > POG', 'Never: Ideal BOH > POG', 'Sometimes: OTL+Casepack-1 > POG', 'Always: OTL+Casepack-1 <= POG', 'Non-POG' ] g = figure(x_range=x_range_list, plot_height=525, plot_width=1200, title="Pog Fit by store", toolbar_location='above', x_axis_label="Date", y_axis_label="Counts", tools=TOOLS_g) g.vbar_stack(pog_fit, x='date_bar', width=0.9, color=colors2, source=source, legend=[value(x) for x in pog_fit], name=pog_fit) g.xaxis.major_label_orientation = 1 g.legend.border_line_width = 3 g.legend.border_line_color = None g.legend.border_line_alpha = 0.5 g.title.text_color = "olive" g.legend.location = "top_right" # BOH vs Pog colors3 = ["#c9d9d3", "#718dbf", "#e84d60"] shelf = [ 'BOH > Shelf Capacity', 'OTL > Shelf Capacity', 'Ideal BOH > Shelf Capacity' ] hover_h = HoverTool( tooltips=[("Location", "@location_reference_id"), ("Date", "@date_bar"), ("OTL > Shelf Capacity", "@OTL_gt_Shelf_Capacity{0,0.00}" ), ("BOH > Shelf Capacity", "@BOH_gt_Shelf_Capacity{0,0.00}"), ("Ideal BOH > Shelf Capacity", "@Ideal_BOH_gt_Shelf_Capacity{0,0.00}")]) TOOLS_h = [ hover_h, BoxZoomTool(), LassoSelectTool(), WheelZoomTool(), PanTool(), ResetTool(), SaveTool() ] h = figure(plot_height=525, plot_width=1000, title="BOH vs Pog by store", x_axis_type="datetime", toolbar_location='above', tools=TOOLS_h, x_axis_label="Date", y_axis_label="Prop") h.background_fill_color = "#e6e9ed" h.background_fill_alpha = 0.5 h.circle(x='date', y='BOH > Shelf Capacity', source=source, fill_color=None, line_color="#4375c6") h.line(x='date', y='BOH > Shelf Capacity', source=source, hover_alpha=0.5, hover_line_color='black', line_width=2, line_color='navy', legend=value("BOH > Shelf Capacity")) h.circle(x='date', y='OTL > Shelf Capacity', source=source, fill_color=None, line_color="#4375c6") h.line(x='date', y='OTL > Shelf Capacity', source=source, hover_alpha=0.5, hover_line_color='black', line_width=2, line_color="green", legend=value("OTL > Shelf Capacity")) h.circle(x='date', y='Ideal BOH > Shelf Capacity', source=source, fill_color=None, line_color="#4375c6") h.line(x='date', y='Ideal BOH > Shelf Capacity', source=source, hover_alpha=0.5, hover_line_color='black', line_width=2, line_color="#e84d60", legend=value("Ideal BOH > Shelf Capacity")) h.legend.border_line_width = 3 h.legend.border_line_color = None h.legend.border_line_alpha = 0.5 h.title.text_color = "olive" h.legend.click_policy = "mute" # Inventory hover_j = HoverTool( tooltips=[("Location", "@location_reference_id"), ( "Date", "@date_bar"), ("DFE_Q98", "@DFE_Q98{0,0.00}"), ("OTL", "@OTL{0,0.00}"), ("EOH", "@EOH{0,0.00}"), ("BOH", "@BOH{0,0.00}")]) TOOLS_j = [ hover_j, BoxZoomTool(), LassoSelectTool(), WheelZoomTool(), PanTool(), ResetTool(), SaveTool() ] j = figure(plot_height=525, plot_width=1200, x_range=x_range_list, title="Inbound/Outbound by store", tools=TOOLS_j, toolbar_location='above', x_axis_label="Date", y_axis_label="Units") j.background_fill_color = "#e6e9ed" j.background_fill_alpha = 0.5 j.vbar(x=dodge('date_bar', -0.40, range=j.x_range), top='DFE_Q98', hover_alpha=0.3, hover_line_color='black', width=0.2, source=source, color="#FBA40A", legend=value("DFE_Q98")) j.vbar(x=dodge('date_bar', -0.20, range=j.x_range), top='OTL', hover_alpha=0.3, hover_line_color='black', width=0.2, source=source, color="#4292c6", legend=value("OTL")) j.vbar(x=dodge('date_bar', 0.00, range=j.x_range), top='EOH', hover_alpha=0.3, hover_line_color='black', width=0.2, source=source, color='#a1dab4', legend=value("EOH")) j.vbar(x=dodge('date_bar', 0.20, range=j.x_range), top='BOH', hover_alpha=0.3, hover_line_color='black', width=0.2, source=source, color="#DC5039", legend=value("BOH")) j.xaxis.major_label_orientation = 1 j.legend.border_line_width = 3 j.legend.border_line_color = None j.legend.border_line_alpha = 0.5 j.title.text_color = "olive" j.legend.location = "top_left" j.legend.click_policy = "mute" #desc.text = " <br > <b> Region:</b> <i> </i> <br /> " pre.text = " <b>Start date:</b> <i>{}</i> <br /> <b>End date:</b> <i>{}</i> <br /> <b>Time period:</b> <i>{}</i> days <br /> <b> Total Number of Nodes:</b> <i>{}</i> <br /> <b>Policy</b> = <i>{}</i><br /> ".format( sdate, edate, days, nodes, policy) #fuction to update data on selection callback = CustomJS(args=dict(source=source, original_source=original_source, location_select_obj=location, region_select_obj=region, div=desc, text_input=text_input), code=""" var data = source.get('data'); var original_data = original_source.get('data'); var loc = location_select_obj.get('value'); var reg = region_select_obj.get('value'); var line = " <br /> <b> Region:</b>"+ reg + "<br /> <b>Location:</b> " + loc; var text_input =text_input.get('value'); div.text=line; for (var key in original_data) { data[key] = []; for (var i = 0; i < original_data['location_reference_id'].length; ++i) { if ((original_data['location_reference_id'][i] === loc) && (original_data['region'][i] === reg) ) { data[key].push(original_data[key][i]); } } } source.trigger('change'); """) #controls = [location, region] #for control in controls: #control.js_on_change("value", callback) #source.js_on_change("value", callback) desc.js_on_event('event', callback) location.js_on_change('value', callback) region.js_on_change('value', callback) text_input.js_on_change('value', callback) #inputs = widgetbox(*controls, sizing_mode="fixed") #inputs = widgetbox(*controls,width=220,height=500) inputs = widgetbox(location, region, desc, pre, width=220, height=500) # controls number of tabs tab1 = Panel(child=p, title='Backroom OH') tab2 = Panel(child=s, title='Stockouts') tab3 = Panel(child=f, title='BOH vs Ideal') tab4 = Panel(child=g, title='Pog Fit') tab5 = Panel(child=m, title='Inbound/Outbound') tab6 = Panel(child=h, title='BOH vs POG') tab7 = Panel(child=t, title='Fill Rate') tab8 = Panel(child=j, title='Inventory') tab9 = Panel(child=w, title='Prop OH in Backroom') #data table columns to summarize data columns = [ TableColumn(field="location_reference_id", title="Location"), TableColumn(field="Backroom_OH", title="Backroom_OH", formatter=NumberFormatter(format="0,0")), TableColumn(field="Outbound", title="Outbound", formatter=NumberFormatter(format="0,0")), TableColumn(field="Inbound", title="Inbound", formatter=NumberFormatter(format="0,0")), TableColumn(field="OTL", title="OTL", formatter=NumberFormatter(format="0,0")), TableColumn(field="DFE_Q98", title="DFE_Q98", formatter=NumberFormatter(format="0,0")), TableColumn(field="BOH", title="BOH", formatter=NumberFormatter(format="0,0")), TableColumn(field="EOH", title="EOH", formatter=NumberFormatter(format="0,0")), TableColumn(field="BOH_OOS", title="BOH_OOS", formatter=NumberFormatter(format="0,0")), TableColumn(field="EOH_OOS", title="EOH_OOS", formatter=NumberFormatter(format="0,0")) ] data_table = DataTable(source=source1, columns=columns, width=1250) tab10 = Panel(child=data_table, title='Summary Table') view = Tabs( tabs=[tab1, tab2, tab5, tab8, tab6, tab3, tab7, tab4, tab9, tab10]) layout_text = column(inputs) layout1 = row(layout_text, view) #laying out plot layout2 = layout(children=[[layout_text, view]], sizing_mode='scale_height') #update plots return layout2
def create_metrics_table(pd_metrics, labels, sample_ids_list): rank_to_sample_pd = get_rank_to_sample_pd(pd_metrics) all_sample_ids = sample_ids_list[:] all_sample_ids.insert(0, '(average over samples)') presence_metrics = [ c.RECALL, c.PRECISION, c.F1_SCORE, c.TP, c.FP, c.FN, c.JACCARD ] estimates_metrics = [c.UNIFRAC, c.UNW_UNIFRAC, c.L1NORM, c.BRAY_CURTIS] alpha_diversity_metics = [c.OTUS, c.SHANNON_DIVERSITY, c.SHANNON_EQUIT] rank_independent_metrics = [c.UNIFRAC, c.UNW_UNIFRAC] all_metrics = [presence_metrics, estimates_metrics, alpha_diversity_metics] presence_metrics_label = 'Presence/absence of taxa' estimates_metrics_label = 'Abundance estimates' alpha_diversity_metics = 'Alpha diversity' all_metrics_labels = [ presence_metrics_label, estimates_metrics_label, alpha_diversity_metics ] styles = [{ 'selector': 'td', 'props': [('width', '77pt')] }, { 'selector': 'th', 'props': [('width', '77pt'), ('text-align', 'left')] }, { 'selector': 'th:nth-child(1)', 'props': [('width', '120pt'), ('font-weight', 'normal')] }, { 'selector': '', 'props': [('width', 'max-content'), ('width', '-moz-max-content'), ('border-top', '1px solid lightgray'), ('border-spacing', '0px')] }, { 'selector': 'expand-toggle:checked ~ * .data', 'props': [('background-color', 'white !important')] }] styles_hidden_thead = styles + [{ 'selector': 'thead', 'props': [('display', 'none')] }] d = { c.RECALL: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.RECALL, c.RECALL), c.PRECISION: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.PRECISION, c.PRECISION), c.F1_SCORE: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.F1_SCORE, c.F1_SCORE), c.TP: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.TP, c.TP), c.FP: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.FP, c.FP), c.FN: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.FN, c.FN), c.JACCARD: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.JACCARD, c.JACCARD), c.UNIFRAC: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.UNIFRAC, c.UNIFRAC), c.UNW_UNIFRAC: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.UNW_UNIFRAC, c.UNW_UNIFRAC), c.L1NORM: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.L1NORM, c.L1NORM), c.BRAY_CURTIS: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.BRAY_CURTIS, c.BRAY_CURTIS), c.OTUS: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.OTUS, c.OTUS), c.SHANNON_DIVERSITY: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.SHANNON_DIVERSITY, c.SHANNON_DIVERSITY), c.SHANNON_EQUIT: '<div class="tooltip">{}<span class="tooltiptext">{}</span></div>'. format(c.SHANNON_EQUIT, c.SHANNON_EQUIT) } pattern = re.compile('|'.join(map(re.escape, d))) def translate(match): return d[match.group(0)] rank_to_sample_to_html = defaultdict(list) for rank in rank_to_sample_pd: for sample_id in all_sample_ids: if sample_id in rank_to_sample_pd[rank]: mydf = rank_to_sample_pd[rank][sample_id] mydf.index.name = None html = '' first_metrics = True for metrics, metrics_label in zip(all_metrics, all_metrics_labels): if rank == 'rank independent': metrics = rank_independent_metrics metrics_label = estimates_metrics_label html += '<p style="margin-bottom: auto"><b>{}</b></p>'.format( metrics_label) mydf_metrics = mydf.loc[metrics] sorted_columns = get_columns(labels, mydf_metrics.columns.tolist()) mydf_metrics = mydf_metrics.loc[:, sorted_columns] if first_metrics: this_style = styles else: this_style = styles_hidden_thead if metrics_label == presence_metrics_label or metrics_label == estimates_metrics_label: html += mydf_metrics.style.apply( get_heatmap_colors, df_metrics=mydf_metrics, axis=1).set_precision(3).set_table_styles( this_style).render() else: html += mydf_metrics.style.set_precision( 3).set_table_styles(this_style).render() if rank == 'rank independent': break first_metrics = False html = pattern.sub(translate, html) rank_to_sample_to_html[rank].append(html) else: rank_to_sample_to_html[rank].append("") mytable1 = Div(text="""<div>{}</div>""".format( rank_to_sample_to_html[c.ALL_RANKS[0]][0]), css_classes=['bk-width-auto']) select_rank = Select(title="Taxonomic rank:", value=c.ALL_RANKS[0], options=c.ALL_RANKS + ['rank independent'], css_classes=['bk-fit-content']) select_sample = Select(title="Sample:", value='0', options=list( zip(map(str, range(len(all_sample_ids))), all_sample_ids)), css_classes=['bk-fit-content']) source = ColumnDataSource(data=rank_to_sample_to_html) select_rank_sample_callback = CustomJS(args=dict(source=source), code=""" mytable1.text = source.data[select_rank.value][select_sample.value]; """) select_rank.js_on_change('value', select_rank_sample_callback) select_sample.js_on_change('value', select_rank_sample_callback) select_rank_sample_callback.args["select_rank"] = select_rank select_rank_sample_callback.args["select_sample"] = select_sample select_rank_sample_callback.args["mytable1"] = mytable1 heatmap_legend = '<img src="heatmap_bar.png" /><div style="text-align:left;font-size: 11px;">Worst<span style="float:right;">Best</span><span style="margin-right: 36px;float:right;">Median</span></div>' heatmap_legend_div = Div(text=heatmap_legend, style={ "width": "155px", "margin-bottom": "-10px" }) # <input type="checkbox" id="expand-toggle" /><label for="expand-toggle" id="expand-btn">Toggle</label> return select_sample, select_rank, heatmap_legend_div, mytable1
def generate_summary_plot(): #x = [x*0.005 for x in range(0, 200)] #y = x x = np.arange(0, 10) #x = [x*0.005 for x in range(0, 200)] y = [i*i for i in x] z = [i*3.0 for i in x] source = ColumnDataSource(data=dict(x=x, y=y)) source2 = ColumnDataSource(data=dict(x=x, z=z)) print(source) print(dict(source=source)) summary_fig = figure(x_axis_location='above', plot_width=400, plot_height=400) line_one = summary_fig.line('x', 'y', source=source, line_width=3, line_alpha=0.6)#, xaxis.axis_label = 'initalized')#,axis.axis_label='title') line_two = summary_fig.line('x', 'z', source=source2, line_width=3, line_alpha=0.6)#, xaxis.axis_label = 'initalized')#,axis.axis_label='title') #selector_options=['alpha','beta','gamma'] #selector1=Select(title='X-Axis',value=selector_options[0],options=selector_options, callback = callback) #summary_fig.xaxis.visible = None xaxis = LinearAxis(axis_label="Initial x-axis label") summary_fig.add_layout(xaxis, 'below') #summary_fig.xaxis.axis_label = 'Time (Years)' #selector1.on_change('value',callback) #plot.yaxis.axis_label = y_title #controls = widgetbox([selector1], width=200) code1 = '''\ object.visible = toggle.active ''' code2 = '''\ object.visible = radio_button.active ''' #var f = cb_obj.value callback2 = CustomJS(args=dict(source=source2), code=""" var data = source.data; var f = cb_obj.value x = data['x'] z = data['z'] if (f == "alpha") { for (i = 0; i < x.length; i++) { z[i] = Math.pow(x[i], 3.)} } else if (f = "beta") { for (i = 0; i < x.length; i++) { z[i] = 20} } source.trigger('change'); """) callback3 = CustomJS(args=dict(xaxis=xaxis), code=""" var f = cb_obj.value xaxis.attributes.axis_label = f xaxis.trigger('change'); """) callback4 = CustomJS(args=dict(source=source2), code=""" var data = source.data; var f = cb_obj.value x = data['x'] z = data['z'] if (f == "A alpha") { for (i = 0; i < x.length; i++) { z[i] = Math.pow(x[i], 3.)} } else if (f = "B alpha") { for (i = 0; i < x.length; i++) { z[i] = 20} } source.trigger('change'); """) callback1 = CustomJS.from_coffeescript(code=code1, args={}) toggle1 = Toggle(label="Green Box", button_type="success", callback=callback1) callback1.args = {'toggle': toggle1, 'object': line_one} #callback2 = CustomJS.from_coffeescript(code=code2, args={}) radio_button_group = RadioButtonGroup(labels=['alpha','beta','gamma'], active=0)# callback=callback2) radio_button_group.js_on_change('value', callback2) #print([method for method in dir(radio_button_group)]) #callback2.args = {'radio_button': radio_button_group, 'object': line_two} #output_file("styling_visible_annotation_with_interaction.html") selector_options = ['A alpha', 'B beta', 'G gamma'] selector1 = Select(title='X-Axis', value=selector_options[0], options=selector_options)#, callback=callback4) selector1.js_on_change('value', callback4) selector2_options = ['Aa alpha', 'Ba beta', 'Ga gamma'] selector2 = Select(title='X-Axis', value=selector_options[0], options=selector2_options)#, callback=callback4) selector2.js_on_change('value', callback3) #slider = Slider(start=0.1, end=4, value=1, step=.1, title="power") #slider.js_on_change('value', callback) controls = widgetbox([toggle1,radio_button_group, selector1, selector2], width=200) layout = row(controls, summary_fig) return layout
class ViewerVIWidgets(object): """ Encapsulates Bokeh widgets, and related callbacks, used for VI """ def __init__(self, title, viewer_cds): self.vi_quality_labels = [ x["label"] for x in vi_flags if x["type"]=="quality" ] self.vi_issue_labels = [ x["label"] for x in vi_flags if x["type"]=="issue" ] self.vi_issue_slabels = [ x["shortlabel"] for x in vi_flags if x["type"]=="issue" ] self.js_files = get_resources('js') self.title = title self.vi_countdown_toggle = None #- List of fields to be recorded in output csv file, contains for each field: # [ field name (in VI file header), associated variable in viewer_cds.cds_metadata ] self.output_file_fields = [] for file_field in vi_file_fields: if file_field[1] in viewer_cds.cds_metadata.data.keys() : self.output_file_fields.append([file_field[0], file_field[1]]) def add_filename(self, username='******'): #- VI file name default_vi_filename = "desi-vi_"+self.title default_vi_filename += ("_"+username) default_vi_filename += ".csv" self.vi_filename_input = TextInput(value=default_vi_filename, title="VI file name:") def add_vi_issues(self, viewer_cds, widgets): #- Optional VI flags (issues) self.vi_issue_input = CheckboxGroup(labels=self.vi_issue_labels, active=[]) vi_issue_code = self.js_files["CSVtoArray.js"] + self.js_files["save_vi.js"] vi_issue_code += """ var issues = [] for (var i=0; i<vi_issue_labels.length; i++) { if (vi_issue_input.active.indexOf(i) >= 0) issues.push(vi_issue_slabels[i]) } if (issues.length > 0) { cds_metadata.data['VI_issue_flag'][ifiberslider.value] = ( issues.join('') ) } else { cds_metadata.data['VI_issue_flag'][ifiberslider.value] = " " } autosave_vi_localStorage(output_file_fields, cds_metadata.data, title) cds_metadata.change.emit() """ self.vi_issue_callback = CustomJS( args=dict(cds_metadata = viewer_cds.cds_metadata, ifiberslider = widgets.ifiberslider, vi_issue_input = self.vi_issue_input, vi_issue_labels = self.vi_issue_labels, vi_issue_slabels = self.vi_issue_slabels, title = self.title, output_file_fields = self.output_file_fields), code = vi_issue_code ) self.vi_issue_input.js_on_click(self.vi_issue_callback) def add_vi_z(self, viewer_cds, widgets): ## TODO: z_tovi behaviour if with_vi_widget=False ..? #- Optional VI information on redshift self.vi_z_input = TextInput(value='', title="VI redshift:") vi_z_code = self.js_files["CSVtoArray.js"] + self.js_files["save_vi.js"] vi_z_code += """ cds_metadata.data['VI_z'][ifiberslider.value]=vi_z_input.value autosave_vi_localStorage(output_file_fields, cds_metadata.data, title) cds_metadata.change.emit() """ self.vi_z_callback = CustomJS( args=dict(cds_metadata = viewer_cds.cds_metadata, ifiberslider = widgets.ifiberslider, vi_z_input = self.vi_z_input, title = self.title, output_file_fields=self.output_file_fields), code = vi_z_code ) self.vi_z_input.js_on_change('value', self.vi_z_callback) # Copy z value from redshift slider to VI self.z_tovi_button = Button(label='Copy z to VI') self.z_tovi_callback = CustomJS( args=dict(z_input=widgets.z_input, vi_z_input=self.vi_z_input), code=""" vi_z_input.value = z_input.value """) self.z_tovi_button.js_on_event('button_click', self.z_tovi_callback) def add_vi_spectype(self, viewer_cds, widgets): #- Optional VI information on spectral type self.vi_category_select = Select(value=' ', title="VI spectype:", options=([' '] + vi_spectypes)) # The default value set to ' ' as setting value='' does not seem to work well with Select. vi_category_code = self.js_files["CSVtoArray.js"] + self.js_files["save_vi.js"] vi_category_code += """ if (vi_category_select.value == ' ') { cds_metadata.data['VI_spectype'][ifiberslider.value]='' } else { cds_metadata.data['VI_spectype'][ifiberslider.value]=vi_category_select.value } autosave_vi_localStorage(output_file_fields, cds_metadata.data, title) cds_metadata.change.emit() """ self.vi_category_callback = CustomJS( args=dict(cds_metadata=viewer_cds.cds_metadata, ifiberslider = widgets.ifiberslider, vi_category_select=self.vi_category_select, title=self.title, output_file_fields=self.output_file_fields), code=vi_category_code ) self.vi_category_select.js_on_change('value', self.vi_category_callback) def add_vi_comment(self, viewer_cds, widgets): #- Optional VI comment self.vi_comment_input = TextInput(value='', title="VI comment (see guidelines):") vi_comment_code = self.js_files["CSVtoArray.js"] + self.js_files["save_vi.js"] vi_comment_code += """ var stored_comment = (vi_comment_input.value).replace(/./g, function(char){ if ( char==',' ) { return ';' } else if ( char.charCodeAt(0)<=127 ) { return char } else { var char_list = ['Å','α','β','γ','δ','λ'] var char_replace = ['Angstrom','alpha','beta','gamma','delta','lambda'] for (var i=0; i<char_list.length; i++) { if ( char==char_list[i] ) return char_replace[i] } return '?' } }) cds_metadata.data['VI_comment'][ifiberslider.value] = stored_comment autosave_vi_localStorage(output_file_fields, cds_metadata.data, title) cds_metadata.change.emit() """ self.vi_comment_callback = CustomJS( args=dict(cds_metadata = viewer_cds.cds_metadata, ifiberslider = widgets.ifiberslider, vi_comment_input = self.vi_comment_input, title=self.title, output_file_fields=self.output_file_fields), code=vi_comment_code ) self.vi_comment_input.js_on_change('value',self.vi_comment_callback) #- List of "standard" VI comment self.vi_std_comment_select = Select(value=" ", title="Standard comment:", options=([' '] + vi_std_comments)) vi_std_comment_code = """ if (vi_std_comment_select.value != ' ') { if (vi_comment_input.value != '') { vi_comment_input.value = vi_comment_input.value + " " + vi_std_comment_select.value } else { vi_comment_input.value = vi_std_comment_select.value } } """ self.vi_std_comment_callback = CustomJS( args = dict(vi_std_comment_select = self.vi_std_comment_select, vi_comment_input = self.vi_comment_input), code = vi_std_comment_code ) self.vi_std_comment_select.js_on_change('value', self.vi_std_comment_callback) def add_vi_quality(self, viewer_cds, widgets): #- Main VI quality widget self.vi_quality_input = RadioButtonGroup(labels=self.vi_quality_labels) vi_quality_code = self.js_files["CSVtoArray.js"] + self.js_files["save_vi.js"] vi_quality_code += """ if ( vi_quality_input.active >= 0 ) { cds_metadata.data['VI_quality_flag'][ifiberslider.value] = vi_quality_labels[vi_quality_input.active] } else { cds_metadata.data['VI_quality_flag'][ifiberslider.value] = "-1" } autosave_vi_localStorage(output_file_fields, cds_metadata.data, title) cds_metadata.change.emit() """ self.vi_quality_callback = CustomJS( args = dict(cds_metadata = viewer_cds.cds_metadata, vi_quality_input = self.vi_quality_input, vi_quality_labels = self.vi_quality_labels, ifiberslider = widgets.ifiberslider, title=self.title, output_file_fields = self.output_file_fields), code=vi_quality_code ) self.vi_quality_input.js_on_click(self.vi_quality_callback) def add_vi_scanner(self, viewer_cds): #- VI scanner name self.vi_name_input = TextInput(value=(viewer_cds.cds_metadata.data['VI_scanner'][0]).strip(), title="Your name (3-letter acronym):") vi_name_code = self.js_files["CSVtoArray.js"] + self.js_files["save_vi.js"] vi_name_code += """ for (var i=0; i<(cds_metadata.data['VI_scanner']).length; i++) { cds_metadata.data['VI_scanner'][i]=vi_name_input.value } var newname = vi_filename_input.value var name_chunks = newname.split("_") newname = ( name_chunks.slice(0,name_chunks.length-1).join("_") ) + ("_"+vi_name_input.value+".csv") vi_filename_input.value = newname autosave_vi_localStorage(output_file_fields, cds_metadata.data, title) """ self.vi_name_callback = CustomJS( args = dict(cds_metadata = viewer_cds.cds_metadata, vi_name_input = self.vi_name_input, vi_filename_input = self.vi_filename_input, title=self.title, output_file_fields = self.output_file_fields), code=vi_name_code ) self.vi_name_input.js_on_change('value', self.vi_name_callback) def add_guidelines(self): #- Guidelines for VI flags vi_guideline_txt = "<B> VI guidelines </B>" vi_guideline_txt += "<BR /> <B> Classification flags: </B>" for flag in vi_flags : if flag['type'] == 'quality' : vi_guideline_txt += ("<BR />  [ "+flag['label']+" ] "+flag['description']) vi_guideline_txt += "<BR /> <B> Optional indications: </B>" for flag in vi_flags : if flag['type'] == 'issue' : vi_guideline_txt += ( "<BR />  [ " + flag['label'] + " (" + flag['shortlabel'] + ") ] " + flag['description'] ) vi_guideline_txt += "<BR /> <B> Comments: </B> <BR /> 100 characters max, avoid commas (automatically replaced by semi-columns), ASCII only." self.vi_guideline_div = Div(text=vi_guideline_txt) def add_vi_storage(self, viewer_cds, widgets): #- Save VI info to CSV file self.save_vi_button = Button(label="Download VI", button_type="success") save_vi_code = self.js_files["FileSaver.js"] + self.js_files["CSVtoArray.js"] + self.js_files["save_vi.js"] save_vi_code += """ download_vi_file(output_file_fields, cds_metadata.data, vi_filename_input.value) """ self.save_vi_callback = CustomJS( args = dict(cds_metadata = viewer_cds.cds_metadata, output_file_fields = self.output_file_fields, vi_filename_input = self.vi_filename_input), code=save_vi_code ) self.save_vi_button.js_on_event('button_click', self.save_vi_callback) #- Recover auto-saved VI data in browser self.recover_vi_button = Button(label="Recover auto-saved VI", button_type="default") recover_vi_code = self.js_files["CSVtoArray.js"] + self.js_files["recover_autosave_vi.js"] self.recover_vi_callback = CustomJS( args = dict(title=self.title, output_file_fields=self.output_file_fields, cds_metadata = viewer_cds.cds_metadata, ifiber = widgets.ifiberslider.value, vi_comment_input = self.vi_comment_input, vi_name_input=self.vi_name_input, vi_quality_input=self.vi_quality_input, vi_issue_input=self.vi_issue_input, vi_issue_slabels=self.vi_issue_slabels, vi_quality_labels=self.vi_quality_labels), code = recover_vi_code ) self.recover_vi_button.js_on_event('button_click', self.recover_vi_callback) #- Clear all auto-saved VI self.clear_vi_button = Button(label="Clear all auto-saved VI", button_type="default") self.clear_vi_callback = CustomJS( args = dict(), code = """ localStorage.clear() """ ) self.clear_vi_button.js_on_event('button_click', self.clear_vi_callback) def add_vi_table(self, viewer_cds): #- Show VI in a table vi_table_columns = [ TableColumn(field="VI_quality_flag", title="Flag", width=40), TableColumn(field="VI_issue_flag", title="Opt.", width=50), TableColumn(field="VI_z", title="VI z", width=50), TableColumn(field="VI_spectype", title="VI spectype", width=150), TableColumn(field="VI_comment", title="VI comment", width=200) ] self.vi_table = DataTable(source=viewer_cds.cds_metadata, columns=vi_table_columns, width=500) self.vi_table.height = 10 * self.vi_table.row_height def add_countdown(self, vi_countdown): #- VI countdown assert vi_countdown > 0 self.vi_countdown_callback = CustomJS(args=dict(vi_countdown=vi_countdown), code=""" if ( (cb_obj.label).includes('Start') ) { // Callback doesn't do anything after countdown started var countDownDate = new Date().getTime() + (1000 * 60 * vi_countdown); var countDownLoop = setInterval(function(){ var now = new Date().getTime(); var distance = countDownDate - now; if (distance<0) { cb_obj.label = "Time's up !"; clearInterval(countDownLoop); } else { var days = Math.floor(distance / (1000 * 60 * 60 * 24)); var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); var seconds = Math.floor((distance % (1000 * 60)) / 1000); //var stuff = days + "d " + hours + "h " + minutes + "m " + seconds + "s "; var stuff = minutes + "m " + seconds + "s "; cb_obj.label = "Countdown: " + stuff; } }, 1000); } """) self.vi_countdown_toggle = Toggle(label='Start countdown ('+str(vi_countdown)+' min)', active=False, button_type="success") self.vi_countdown_toggle.js_on_change('active', self.vi_countdown_callback)
def make_plot(emperor, df, column=None, value=None): df = df[df['Emperor'] == emperor] source = ColumnDataSource(df) select_den = Select(title="Denomination", value="All", options=["All", "Aureus", "Denarius"]) select_grd = Select(title="Grade", value="All", options=[ 'All', 'Fine', 'Good Fine', 'Near VF', 'VF', 'Good VF', 'Near EF', 'EF', 'Superb EF', 'Choice EF', 'FDC' ]) check_attractive = CheckboxGroup(labels=["Attractively Toned"], active=[]) check_cabinet = CheckboxGroup(labels=["Cabinet Toning"], active=[]) check_lusterous = CheckboxGroup(labels=["Lusterous"], active=[]) check_centered = CheckboxGroup(labels=["Well Centered"], active=[]) check_portrait = CheckboxGroup(labels=["Artistic Portrait"], active=[]) # This callback is crucial, otherwise the filter will # not be triggered when the select changes callback = CustomJS(args=dict(source=source), code=""" source.change.emit(); """) select_den.js_on_change('value', callback) select_grd.js_on_change('value', callback) check_attractive.js_on_change('active', callback) check_cabinet.js_on_change('active', callback) check_lusterous.js_on_change('active', callback) check_centered.js_on_change('active', callback) check_portrait.js_on_change('active', callback) custom_filter_grd = CustomJSFilter(args=dict(select=select_grd, source=source), code=''' var indices = []; console.log(select.value); // no select cuts applied if (select.value == 'All') { for (var i = 0; i < source.get_length(); i++){ indices.push(true); } return indices; } // iterate through rows of data source and see if each satisfies some constraint for (var i = 0; i < source.get_length(); i++){ if (source.data['Grade'][i] == select.value){ indices.push(true); } else { indices.push(false) } } return indices; ''') custom_filter_den = CustomJSFilter(args=dict(select=select_den, source=source), code=''' var indices = []; console.log(select.value); // no select cuts applied if (select.value == 'All') { for (var i = 0; i < source.get_length(); i++){ indices.push(true); } return indices; } // iterate through rows of data source and see if each satisfies some constraint for (var i = 0; i < source.get_length(); i++){ if (source.data['Denomination'][i] == select.value){ indices.push(true); } else { indices.push(false) } } //console.log(indices) return indices; ''') custom_filter_attractive = CustomJSFilter(args=dict( checkbox=check_attractive, source=source), code=''' var indices = []; //console.log(checkbox.active); if (checkbox.active.includes(0)) { //console.log('0 on') //console.log(checkbox.active.includes(0)); for (var i = 0; i < source.get_length(); i++) { if (source.data['Attractively Toned'][i] == 1) { indices.push(true); } else { indices.push(false) } } } else { //console.log('0 off') for (var i = 0; i < source.get_length(); i++) { indices.push(true); } } return indices; ''') custom_filter_cabinet = CustomJSFilter(args=dict(checkbox=check_cabinet, source=source), code=''' var indices = []; //console.log(checkbox.active); if (checkbox.active.includes(0)) { //console.log('0 on') //console.log(checkbox.active.includes(0)); for (var i = 0; i < source.get_length(); i++) { if (source.data['Cabinet Toning'][i] == 1) { indices.push(true); } else { indices.push(false) } } } else { //console.log('0 off') for (var i = 0; i < source.get_length(); i++) { indices.push(true); } } return indices; ''') custom_filter_lusterous = CustomJSFilter(args=dict( checkbox=check_lusterous, source=source), code=''' var indices = []; //console.log(checkbox.active); if (checkbox.active.includes(0)) { //console.log('0 on') //console.log(checkbox.active.includes(0)); for (var i = 0; i < source.get_length(); i++) { if (source.data['Lusterous'][i] == 1) { indices.push(true); } else { indices.push(false) } } } else { //console.log('0 off') for (var i = 0; i < source.get_length(); i++) { indices.push(true); } } return indices; ''') custom_filter_centered = CustomJSFilter(args=dict(checkbox=check_centered, source=source), code=''' var indices = []; //console.log(checkbox.active); if (checkbox.active.includes(0)) { //console.log('0 on') //console.log(checkbox.active.includes(0)); for (var i = 0; i < source.get_length(); i++) { if (source.data['Cabinet Toning'][i] == 1) { indices.push(true); } else { indices.push(false) } } } else { //console.log('0 off') for (var i = 0; i < source.get_length(); i++) { indices.push(true); } } return indices; ''') custom_filter_portrait = CustomJSFilter(args=dict(checkbox=check_portrait, source=source), code=''' var indices = []; //console.log(checkbox.active); if (checkbox.active.includes(0)) { //console.log('0 on') //console.log(checkbox.active.includes(0)); for (var i = 0; i < source.get_length(); i++) { if (source.data['Quality Portrait'][i] == 1) { indices.push(true); } else { indices.push(false) } } } else { //console.log('0 off') for (var i = 0; i < source.get_length(); i++) { indices.push(true); } } return indices; ''') view = CDSView(source=source, filters=[ custom_filter_grd, custom_filter_den, custom_filter_attractive, custom_filter_cabinet, custom_filter_lusterous, custom_filter_centered, custom_filter_portrait ]) TOOLS = ["pan, wheel_zoom, box_zoom, reset, save"] TOOLTIPS = [("Auction", "@AuctionID"), ("Lot", "@LotNumber"), ("Emperor", "@Emperor"), ("RIC Number", "@RIC"), ("Estimate [USD]", "@Estimate"), ("Sale [USD]", "@Sale")] plot = figure( title='CNG Auctions through 2019 for Coins of Emperor ' + emperor, plot_width=500, plot_height=300, tools=TOOLS, tooltips=TOOLTIPS, x_range=Range1d(start=20, end=80000, bounds=(None, None)), y_range=[ 'Fine', 'Good Fine', 'Near VF', 'VF', 'Good VF', 'Near EF', 'EF', 'Superb EF', 'Choice EF', 'FDC' ], x_axis_type='log') color_mapper = CategoricalColorMapper(factors=['Aureus', 'Denarius'], palette=['#FFD700', '#C0C0C0']) plot.circle(x='Sale', y=jitter('Grade', 0.4, range=plot.y_range), source=source, view=view, fill_alpha=0.8, size=5, legend='data', line_color=None, color={ 'field': 'Denomination', 'transform': color_mapper }, hover_color='red') plot.xaxis.axis_label = "Sale Price (USD)" plot.yaxis.axis_label = "Grade" plot.xaxis.formatter = BasicTickFormatter(use_scientific=False) plot.xaxis.formatter = NumeralTickFormatter(format='$0,0') plot.legend.visible = False return row( plot, widgetbox([ select_den, select_grd, check_attractive, check_cabinet, check_lusterous, check_centered, check_portrait ]))
new_val = predict_data['proba'] console.log('Success:', predict_data) data['new_y'][0] = new_val.toFixed(1) data['y_perc'][0] = new_val.toFixed(1)+"%" source.change.emit() }) .catch((err) => { console.log('Err', err) }); """) # Initiate callback with any value changes age_radio.js_on_change('active', callback) sex_radio.js_on_change('active', callback) country_dropdown.js_on_change('value', callback) edu_dropdown.js_on_change('value', callback) n_slider.js_on_change('value', callback) e_slider.js_on_change('value', callback) o_slider.js_on_change('value', callback) c_slider.js_on_change('value', callback) a_slider.js_on_change('value', callback) s_slider.js_on_change('value', callback) i_slider.js_on_change('value', callback) # List of all sliders sliders = [ n_slider, e_slider, o_slider, c_slider,
p.xaxis.major_label_text_font_size = '15pt' p.legend.location = "bottom_right" p.legend.orientation = "vertical" p.legend.border_line_color = "black" ### add the select category option ### callback = CustomJS(args={ 'source': source, 'data': data }, code="""source.data = data[cb_obj.value]""") color_select = Select(title="Select Category", value="Style", options=["Style", "Category", "Face or body"]) color_select.js_on_change('value', callback) ### add hover and tap tools ### hover = HoverTool( tooltips=[('Art Title', '@title'), ('Category', '@info'), ('Positive', '@pos'), ('Negative', '@neg')]) taptool = TapTool() tap_code = """ var selected= source.selected['1d'].indices; // console.log('tap, you selected:', data_source['Style'][selected]) var data = source.data, selected = source.selected.indices,
def _plot(self, runs): """Create table and plot that reacts to selection of cells by updating the plotted data to visualize correlation. Parameters ---------- runs: List[ConfiguratorRun] list with runs (budgets) to be compared """ df = self._get_table(runs) # Create CDS from pandas dataframe budget_names = list(df.columns.values) data = dict(df[budget_names]) data["Budget"] = df.index.tolist() table_source = ColumnDataSource(data) # Create bokeh-datatable columns = [ TableColumn( field='Budget', title="Budget", sortable=False, width=20) ] + [ TableColumn(field=header, title=header, default_sort='descending', width=10) for header in budget_names ] bokeh_table = DataTable(source=table_source, columns=columns, index_position=None, sortable=False, height=20 + 30 * len(data["Budget"])) # Create CDS for scatter-plot all_configs = set([ a for b in [run.original_runhistory.get_all_configs() for run in runs] for a in b ]) data = { os.path.basename(run.folder).replace('_', ' '): [ run.original_runhistory.get_cost(c) if c in # TODO run.original_runhistory.get_all_configs() else None for c in all_configs ] for run in runs } data['x'] = [] data['y'] = [] # Default scatter should be lowest vs highest: for x, y in zip(data[budget_names[0]], data[budget_names[-1]]): if x is not None and y is not None: data['x'].append(x) data['y'].append(y) with warnings.catch_warnings(record=True) as list_of_warnings: # Catch unmatching column lengths warning warnings.simplefilter('always') scatter_source = ColumnDataSource(data=data) for w in list_of_warnings: self.logger.debug( "During budget correlation a %s was raised: %s", str(w.category), w.message) # Create figure and dynamically updating plot (linked with table) min_val = min([ min([v for v in val if v]) for val in data.values() if len(val) > 0 ]) max_val = max([ max([v for v in val if v]) for val in data.values() if len(val) > 0 ]) padding = ( max_val - min_val ) / 10 # Small padding to border (fraction of total intervall) min_val -= padding max_val += padding p = figure(plot_width=400, plot_height=400, match_aspect=True, y_range=Range1d(start=min_val, end=max_val, bounds=(min_val, max_val)), x_range=Range1d(start=min_val, end=max_val, bounds=(min_val, max_val)), x_axis_label=budget_names[0], y_axis_label=budget_names[-1]) p.circle( x='x', y='y', #x=jitter('x', 0.1), y=jitter('y', 0.1), source=scatter_source, size=5, color="navy", alpha=0.5) code_budgets = 'var budgets = ' + str( budget_names) + '; console.log(budgets);' code_try = 'try {' code_get_selected_cell = """ // This first part only extracts selected row and column! var grid = document.getElementsByClassName('grid-canvas')[0].children; var row = ''; var col = ''; for (var i=0,max=grid.length;i<max;i++){ if (grid[i].outerHTML.includes('active')){ row=i; for (var j=0,jmax=grid[i].children.length;j<jmax;j++){ if(grid[i].children[j].outerHTML.includes('active')){col=j} } } } col = col - 1; console.log('row', row, budgets[row]); console.log('col', col, budgets[col]); table_source.selected.indices = []; // Reset, so gets triggered again when clicked again """ code_selected = """ row = budgets.indexOf(select_x.value); col = budgets.indexOf(select_y.value); """ code_update_selection_values = """ select_x.value = budgets[row]; select_y.value = budgets[col]; """ code_update_plot = """ // This is the actual updating of the plot if (row => 0 && col > 0) { // Copy relevant arrays var new_x = scatter_source.data[budgets[row]].slice(); var new_y = scatter_source.data[budgets[col]].slice(); // Remove all pairs where one value is null while ((next_null = new_x.indexOf(null)) > -1) { new_x.splice(next_null, 1); new_y.splice(next_null, 1); } while ((next_null = new_y.indexOf(null)) > -1) { new_x.splice(next_null, 1); new_y.splice(next_null, 1); } // Assign new data to the plotted columns scatter_source.data['x'] = new_x; scatter_source.data['y'] = new_y; scatter_source.change.emit(); // Update axis-labels xaxis.attributes.axis_label = budgets[row]; yaxis.attributes.axis_label = budgets[col]; // Update ranges var min = Math.min(...[Math.min(...new_x), Math.min(...new_y)]) max = Math.max(...[Math.max(...new_x), Math.max(...new_y)]); var padding = (max - min) / 10; console.log(min, max, padding); xr.start = min - padding; yr.start = min - padding; xr.end = max + padding; yr.end = max + padding; } """ code_catch = """ } catch(err) { console.log(err.message); } """ code_selected = code_budgets + code_try + code_selected + code_update_plot + code_catch select_x = Select(title="X-axis:", value=budget_names[0], options=budget_names) select_y = Select(title="Y-axis:", value=budget_names[-1], options=budget_names) callback_select = CustomJS(args=dict( scatter_source=scatter_source, select_x=select_x, select_y=select_y, xaxis=p.xaxis[0], yaxis=p.yaxis[0], xr=p.x_range, yr=p.y_range, ), code=code_selected) select_x.js_on_change('value', callback_select) select_y.js_on_change('value', callback_select) code_table_cell = code_budgets + code_try + code_get_selected_cell + code_update_selection_values + code_update_plot + code_catch callback_table_cell = CustomJS(args=dict( table_source=table_source, scatter_source=scatter_source, select_x=select_x, select_y=select_y, xaxis=p.xaxis[0], yaxis=p.yaxis[0], xr=p.x_range, yr=p.y_range, ), code=code_table_cell) table_source.selected.js_on_change('indices', callback_table_cell) layout = column(bokeh_table, row(p, column(select_x, select_y))) return layout
'condition_filter': condition_filter, 'cog_class_filter': cog_class_filter, 'condition_view': condition_view, 'cog_desc_view': cog_desc_view, 'selection': selection, 'cog_class_treemap': class_treemap } selection_callback = CustomJS(args=args, code=selection_cb + class_click_cb + desc_click_cb) class_click_callback = CustomJS(args=args, code=class_click_cb + desc_click_cb + selection_cb) desc_click_callback = CustomJS(args=args, code=desc_click_cb + class_click_cb + selection_cb) # Assign the callbacks to the interactions class_click_event = class_treemap.select(type=TapTool) desc_click_event = desc_treemap.select(type=TapTool) class_click_event.callback = class_click_callback desc_click_event.callback = desc_click_callback selection.js_on_change('value', selection_callback) row = bokeh.layouts.row(class_treemap, desc_treemap, gene_treemap) col = bokeh.layouts.column(selection, row) lay = bokeh.layouts.row(col) bokeh.io.save(lay) # %%
def plot_chart_bokeh(processed, dataCollection, keys, outputfilename): stock = processed['data'] # Define constants W_PLOT = 1000 H_PLOT = 360 TOOLS = 'pan,wheel_zoom,reset' VBAR_WIDTH = 1 * 12 * 60 * 60 * 1000 # one day in ms RED = Category20[7][6] GREEN = Category20[5][4] BLUE = Category20[3][0] BLUE_LIGHT = Category20[3][1] ORANGE = Category20[3][2] PURPLE = Category20[9][8] BROWN = Category20[11][10] # ========================================================================== # =================== PLOT CANDLE STICK GRAPH ==================== # ========================================================================== p1 = figure(plot_width=W_PLOT, plot_height=H_PLOT, tools=TOOLS, toolbar_location='right') inc = stock.data['Close'] >= stock.data['Open'] dec = stock.data['Open'] > stock.data['Close'] # limit = stock.data['ZC_d2/dt2'] > 10 # limit = stock.data['ZC_d/dt'] > 0 # view_inc = CDSView(source=stock, filters=[BooleanFilter(inc), BooleanFilter(limit)]) # view_dec = CDSView(source=stock, filters=[BooleanFilter(dec), BooleanFilter(limit)]) view_inc = CDSView(source=stock, filters=[BooleanFilter(inc)]) view_dec = CDSView(source=stock, filters=[BooleanFilter(dec)]) # # map dataframe indices to date strings and use as label overrides p1.y_range.start = 0.9 * min(stock.data['Low']) p1.y_range.end = 1.1 * max(stock.data['High']) p1.segment(x0='Date', x1='Date', y0='Low', y1='High', color=GREEN, source=stock, view=view_inc) p1.segment(x0='Date', x1='Date', y0='Low', y1='High', color=RED, source=stock, view=view_dec) vb1 = p1.vbar(x='Date', width=VBAR_WIDTH, top='Open', bottom='Close', fill_color='forestgreen', fill_alpha=1, line_color='forestgreen', source=stock, view=view_inc, name="price") vb2 = p1.vbar(x='Date', width=VBAR_WIDTH, top='Open', bottom='Close', fill_color='orangered', fill_alpha=1, line_color='orangered', source=stock, view=view_dec, name="price") # Bollinger band plot patch1 = p1.varea(x='Date', y1='lowerband', y2='upperband', source=stock, fill_alpha=0.05, fill_color='dodgerblue') patch_line1 = p1.line(x='Date', y='lowerband', source=stock, line_color='blue', line_alpha=0.4) patch_line2 = p1.line(x='Date', y='middleband', source=stock, line_color='grey', line_alpha=0.8, line_dash='dotdash') patch_line3 = p1.line(x='Date', y='upperband', source=stock, line_color='blue', line_alpha=0.4) # ZC Line plot zc_7 = p1.line(x='Date', y='ma7', source=stock, line_color='crimson', line_alpha=0.4) zc_26 = p1.line(x='Date', y='ma26', source=stock, line_color='darkslateblue', line_alpha=0.4) # # Resistance plots # r1 = p1.line(x='Date', y='r1', source=stock, line_color='forestgreen', line_dash='dotdash', line_alpha=0.6) # r2 = p1.line(x='Date', y='r2', source=stock, line_color='forestgreen', line_dash='dotdash', line_alpha=0.8) # r3 = p1.line(x='Date', y='r3', source=stock, line_color='forestgreen', line_dash='dotdash', line_alpha=1.0) # # Support plots # s1 = p1.line(x='Date', y='s1', source=stock, line_color='crimson', line_dash='dotdash', line_alpha=0.6) # s2 = p1.line(x='Date', y='s2', source=stock, line_color='crimson', line_dash='dotdash', line_alpha=0.8) # s3 = p1.line(x='Date', y='s3', source=stock, line_color='crimson', line_dash='dotdash', line_alpha=1.0) # Extrema plots # minima = p1.inverted_triangle(x='Date', y='minima', source=stock, size=5, color="goldenrod", alpha=0.5) # maxima = p1.triangle(x='Date', y='maxima', source=stock, size=5, color="teal", alpha=0.5) # minima = p1.circle( # x='Date', y='minima', source=stock, size=10, # fill_color="grey", hover_fill_color="firebrick", # fill_alpha=0.2, hover_alpha=0.8, hover_line_color="white") # maxima = p1.triangle( # x='Date', y='maxima', source=stock, # size=10, fill_color="grey", fill_alpha=0.2, # hover_fill_color="firebrick", hover_alpha=0.8, hover_line_color="white") # Volume plot # Setting the second y axis range name and range p1.extra_y_ranges = { "vol_axis": Range1d(start=0, end=max(stock.data['Volume']) * 4) } # Adding the second axis to the plot. p1.add_layout(LinearAxis(y_range_name="vol_axis", visible=False), 'right') vol_inc = p1.vbar(x="Date", top="Volume", bottom=0, width=int(VBAR_WIDTH * 2), fill_color=GREEN, fill_alpha=0.1, line_color=GREEN, line_alpha=0.2, source=stock, view=view_inc, y_range_name="vol_axis") vol_dec = p1.vbar(x="Date", top="Volume", bottom=0, width=int(VBAR_WIDTH * 2), fill_color=RED, fill_alpha=0.1, line_color=RED, line_alpha=0.2, source=stock, view=view_dec, y_range_name="vol_axis") legend = Legend(items=[ LegendItem( label="All", renderers=[ patch1, patch_line1, patch_line2, patch_line3, vol_inc, vol_dec, zc_7, zc_26, # s1, s2, s3,r1, r2, r3, # minima, maxima ], index=0), LegendItem(label="BB", renderers=[patch1, patch_line1, patch_line2, patch_line3], index=1), LegendItem(label="Volume", renderers=[vol_inc, vol_dec], index=2), LegendItem(label="ZC", renderers=[zc_7, zc_26], index=3), LegendItem(label="MA7", renderers=[zc_7], index=4), LegendItem(label="MA26", renderers=[zc_26], index=5), # LegendItem(label="Support", renderers=[s1, s2, s3], index=6), # LegendItem(label="Resistance", renderers=[r1, r2, r3], index=7), # LegendItem(label="Extrema", renderers=[minima, maxima], index=8) ]) p1.add_layout(legend) p1.legend.location = "top_left" p1.legend.border_line_alpha = 0 p1.legend.background_fill_alpha = 0 p1.legend.click_policy = "hide" p1.legend.orientation = "horizontal" # p1.add_layout(Title(text="Stock price", align="left"), "left") p1.yaxis.axis_label = 'Stock price' p1.yaxis.formatter = NumeralTickFormatter(format='0.00') p1.x_range.range_padding = 0.05 p1.xaxis.ticker.desired_num_ticks = 40 p1.xaxis.major_label_orientation = 3.14 / 4 p1.xaxis.visible = False p1.xgrid.grid_line_color = None p1.ygrid.grid_line_color = None # Select specific tool for the plot p1.add_tools( HoverTool( tooltips=[("Datetime", "@Date{%Y-%m-%d}"), ("Open", "@Open{0,0.00}"), ("Close", "@Close{0,0.00}"), ("Volume", "@Volume{(0.00 a)}")], formatters={"@Date": 'datetime'}, # display a tooltip whenever the cursor is vertically in line with a glyph mode='vline', renderers=[vb1, vb2])) # ========================================================================== # =================== PLOT STOCH / RSI GRAPH ================= # ========================================================================== p2 = figure(plot_width=W_PLOT, plot_height=int(H_PLOT / 4), tools=TOOLS, toolbar_location='above', x_range=p1.x_range, x_axis_type='datetime') # , y_range=(-20, 120) stoch_k = p2.line(x='Date', y='slowk', source=stock, line_color='royalblue', alpha=0.8, muted_alpha=0.2) stoch_d = p2.line(x='Date', y='slowd', source=stock, line_color='tomato', alpha=0.8, muted_alpha=0.2) rsi = p2.line(x='Date', y='rsi', source=stock, line_color='gray', alpha=0.8, muted_alpha=0.2) mid_box = BoxAnnotation(bottom=20, top=80, fill_alpha=0.2, fill_color='palegreen', line_color='lightcoral', line_alpha=0.4, line_dash='dashed') # candle = p2.line(x='Date', y='candle', source=stock, line_color='royalblue', alpha=0.8, muted_alpha=0.2) # mid_box = BoxAnnotation(bottom=-300, top=300, fill_alpha=0.2, fill_color='palegreen', line_color='lightcoral', line_alpha=0.4, line_dash='dashed') legend = Legend(items=[ LegendItem(label="Stoch", renderers=[stoch_k, stoch_d], index=0), LegendItem(label="RSI", renderers=[rsi], index=1) # LegendItem(label="Candle", renderers=[candle], index=1) ]) p2.add_layout(legend) p2.add_layout(mid_box) # p2.add_layout(lower) zero = Span(location=0, dimension='width', line_color='seagreen', line_dash='solid', line_width=0.8) p2.add_layout(zero) p2.yaxis.axis_label = 'Stochastic / RSI' p2.x_range.range_padding = 0.05 # p2.toolbar.autohide = True p2.xaxis.visible = False p2.legend.location = "top_left" p2.legend.border_line_alpha = 0 p2.legend.background_fill_alpha = 0 p2.legend.click_policy = "mute" p2.xgrid.grid_line_color = None p2.ygrid.grid_line_color = None # ========================================================================== # =================== Plot MACD ==================== # ========================================================================== y_limit = abs(max(stock.data['macd_hist'], key=abs)) y2_limit = abs(max(stock.data['macd_d/dt'], key=abs)) p3 = figure(plot_width=W_PLOT, plot_height=int(H_PLOT / 2.5), tools=TOOLS, toolbar_location='above', x_range=p1.x_range, x_axis_type='datetime', y_range=(-y_limit, y_limit)) mapper = LinearColorMapper(palette=Viridis256) macd_line = p3.line(x='Date', y='macd_hist', source=stock, line_color='darkgreen', alpha=0.8, muted_alpha=0.2) # macd_hist = p3.vbar_stack(['macd'], x='Date', source=stock, width=int(VBAR_WIDTH * 2), fill_color={'field':'macd', 'transform': mapper}) mid_box = BoxAnnotation(bottom=-0.5, top=0.5, fill_alpha=0.2, fill_color='blanchedalmond', line_color='grey', line_alpha=0.4, line_dash='dashed') zero = Span(location=0, dimension='width', line_color='seagreen', line_dash='solid', line_width=0.8) p3.add_layout(zero) p3.add_layout(mid_box) # Setting the second y axis range name and range p3.extra_y_ranges = { "extra_y_axis": Range1d(start=-y2_limit, end=y2_limit) } # Adding the second axis to the plot. p3.add_layout(LinearAxis(y_range_name="extra_y_axis"), 'right') macd_v = p3.line(x='Date', y='macd_d/dt', source=stock, line_color='dodgerblue', line_dash='solid', alpha=0.8, muted_alpha=0.2, y_range_name="extra_y_axis") macd_acc = p3.line(x='Date', y='macd_d2/dt2', source=stock, line_color='tomato', line_dash='dotdash', alpha=0.8, muted_alpha=0.2, y_range_name="extra_y_axis") legend = Legend(items=[ LegendItem(label="MACD", renderers=[macd_line], index=0), LegendItem(label="MACD-v", renderers=[macd_v], index=1), LegendItem(label="MACD-a", renderers=[macd_acc], index=2) ]) p3.add_layout(legend) p3.legend.location = "top_left" p3.legend.border_line_alpha = 0 p3.legend.background_fill_alpha = 0 p3.legend.click_policy = "mute" p3.legend.orientation = "horizontal" # p3.add_layout(Title(text="MACD", align="center"), "left") p3.yaxis.axis_label = 'MACD' p3.x_range.range_padding = 0.05 p3.xaxis.visible = False p3.xaxis.ticker.desired_num_ticks = 40 p3.xaxis.major_label_orientation = 3.14 / 4 p3.toolbar.autohide = True p3.xgrid.grid_line_color = None p3.ygrid.grid_line_color = None # ========================================================================== # =================== Plot ZC ==================== # ========================================================================== y_limit = abs(max(stock.data['ZC'], key=abs)) y2_limit = abs(max(stock.data['ZC_d/dt'], key=abs)) # y_limit = abs(max(stock.data['slowk'], key=abs)) # y2_limit = abs(max(stock.data['slowk_d/dt'], key=abs)) p4 = figure(plot_width=W_PLOT, plot_height=int(H_PLOT / 3), tools=TOOLS, toolbar_location='above', x_range=p1.x_range, x_axis_type='datetime', y_range=(-y_limit, y_limit)) p4.xaxis.formatter = DatetimeTickFormatter( hours=["%d.%m.%y"], days=["%d.%m.%y"], months=["%d.%m.%y"], years=["%d.%m.%y"], ) # macd_v = p4.line(x='Date', y='macd_d/dt', source=stock, line_color='royalblue', alpha=0.8, muted_alpha=0.2) # macd_acc = p4.line(x='Date', y='macd_d2/dt2', source=stock, line_color='tomato', alpha=0.8, muted_alpha=0.2) # ad = p4.line(x='Date', y='ck_AD', source=stock, line_color='royalblue', alpha=0.8, muted_alpha=0.2) # adosc = p4.line(x='Date', y='ck_ADOSC', source=stock, line_color='tomato', alpha=0.8, muted_alpha=0.2) # obv = p4.line(x='Date', y='OBV', source=stock, line_color='darkgreen', alpha=0.8, muted_alpha=0.2) # Setting the second y axis range name and range p4.extra_y_ranges = { "extra_y_axis": Range1d(start=-y2_limit, end=y2_limit) } # Adding the second axis to the plot. p4.add_layout(LinearAxis(y_range_name="extra_y_axis"), 'right') zc = p4.line(x='Date', y='ZC', source=stock, line_color='darkgreen', alpha=0.8, muted_alpha=0.2) zc_v = p4.line(x='Date', y='ZC_d/dt', source=stock, line_color='dodgerblue', line_dash='dotdash', alpha=0.8, muted_alpha=0.2, y_range_name="extra_y_axis") zc_a = p4.line(x='Date', y='ZC_d2/dt2', source=stock, line_color='tomato', line_dash='dotdash', alpha=0.8, muted_alpha=0.2, y_range_name="extra_y_axis") # slowk = p4.line(x='Date', y='slowk', source=stock, line_color='darkgreen', alpha=0.8, muted_alpha=0.2) # slowk_v = p4.line(x='Date', y='slowk_d/dt', source=stock, line_color='dodgerblue', line_dash='dotdash', alpha=0.8, muted_alpha=0.2, y_range_name="extra_y_axis") # slowk_a = p4.line(x='Date', y='slowk_d2/dt2', source=stock, line_color='tomato', line_dash='dotdash', alpha=0.8, muted_alpha=0.2, y_range_name="extra_y_axis") mid_box = BoxAnnotation(bottom=-0.5, top=0.5, fill_alpha=0.2, fill_color='blanchedalmond', line_color='grey', line_alpha=0.4, line_dash='dashed') zero = Span(location=0, dimension='width', line_color='seagreen', line_dash='solid', line_width=0.8) p4.add_layout(zero) p4.add_layout(mid_box) # p4.yaxis.axis_label = 'MACD v/acc' legend = Legend(items=[ LegendItem(label="ZC", renderers=[zc], index=0), LegendItem(label="ZC-v", renderers=[zc_v], index=1), LegendItem(label="ZC-a", renderers=[zc_a], index=2), # LegendItem(label="slowk", renderers=[slowk], index=0), # LegendItem(label="slowk-v", renderers=[slowk_v], index=1), # LegendItem(label="slowk-a", renderers=[slowk_a], index=2) ]) p4.add_layout(legend) p4.legend.location = "top_left" p4.legend.border_line_alpha = 0 p4.legend.background_fill_alpha = 0 p4.legend.click_policy = "mute" p4.legend.orientation = "horizontal" p4.x_range.range_padding = 0.05 p4.xaxis.ticker.desired_num_ticks = 40 p4.xaxis.major_label_orientation = 3.14 / 4 p4.toolbar.autohide = True p4.xgrid.grid_line_color = None p4.ygrid.grid_line_color = None addSpans([p1, p2, p3, p4]) columns = [ TableColumn(field="Date", title="Date", formatter=DateFormatter(format='%d.%b')), # TableColumn(field="Open", title="Open", formatter=NumberFormatter(format='0.00')), # TableColumn(field="Close", title="Close", formatter=NumberFormatter(format='0.00')), TableColumn(field="ZC", title="ZC", formatter=NumberFormatter(format='0.000', text_align='right')), TableColumn(field="ZC_d/dt", title="ZC-v", formatter=NumberFormatter(format='0.000', text_align='right')), TableColumn(field="macd_hist", title="MACD", formatter=NumberFormatter(format='0.000', text_align='right')), TableColumn(field="macd_d/dt", title="MACD-v", formatter=NumberFormatter(format='0.000', text_align='right')), # TableColumn(field="macd_d2/dt2", title="MACD-a", formatter=NumberFormatter(format='0.000')), TableColumn(field="stoch", title="STOCH", formatter=NumberFormatter(format='0.0', text_align='right')), TableColumn(field="stoch-v", title="STOCH-v", formatter=NumberFormatter(format='0.0', text_align='right')), # TableColumn(field="slowk_d/dt", title="slowk-v", formatter=NumberFormatter(format='0.000')), # TableColumn(field="slowk_d2/dt2", title="slowk-a", formatter=NumberFormatter(format='0.000')), ] data_table = DataTable(source=stock, columns=columns, width=int(W_PLOT / 3), height=int(H_PLOT * 2.2), index_position=None, width_policy='min') # ========================================================================== # =================== SELECT WIDGET ==================== # ========================================================================== callback_select_main = """ var d0 = s0.data; var symbol = cb_obj.value.split(" ")[0] var data_all = dataCollection[symbol] var data = data_all.data.data; /// Iterate over keys in new data and reassign old data with new data for (const key of Object.keys(data)) { d0[key] = [] d0[key] = data[key] } s0.change.emit() /// Update y-axes range plot.y_range.have_updated_interactively = true plot.y_range.start = 0.9 * Math.min(...data['Low']) plot.y_range.end = 1.1 * Math.max(...data['High']) plot.extra_y_ranges['vol_axis'].have_updated_interactively = true plot.extra_y_ranges['vol_axis'].start = 0 plot.extra_y_ranges['vol_axis'].end = Math.max(...data['Volume']) * 4 """ callback_select_va = """ var symbol = cb_obj.value.split(" ")[0] var data_all = dataCollection[symbol] var data = data_all.data.data; var y_limit = Math.max.apply(null, data[param_main].map(Math.abs)); var y_extra_limit = Math.max.apply(null, data[param_extra].map(Math.abs)); /// Update y-axes range plot.y_range.have_updated_interactively = true plot.y_range.start = -y_limit plot.y_range.end = y_limit plot.extra_y_ranges['extra_y_axis'].have_updated_interactively = true plot.extra_y_ranges['extra_y_axis'].start = -y_extra_limit plot.extra_y_ranges['extra_y_axis'].end = y_extra_limit """ selecthandler_main = CustomJS(args={ 's0': stock, 'dataCollection': dataCollection, 'plot': p1 }, code=callback_select_main) selecthandler_p3 = CustomJS(args={ 'dataCollection': dataCollection, 'plot': p3, 'param_main': 'macd_hist', 'param_extra': 'macd_d/dt' }, code=callback_select_va) selecthandler_p4 = CustomJS(args={ 'dataCollection': dataCollection, 'plot': p4, 'param_main': 'ZC', 'param_extra': 'ZC_d/dt' }, code=callback_select_va) # selecthandler_p4 = CustomJS(args={'dataCollection':dataCollection, 'plot':p4, 'param_main': 'slowk', 'param_extra': 'slowk_d/dt'}, code = callback_select_va) select = Select(title="Select:", value=keys[0], options=keys) select.js_on_change('value', selecthandler_main) select.js_on_change('value', selecthandler_p3) select.js_on_change('value', selecthandler_p4) # [cleanDate(x, stock.data) for x in [p1, p2, p3, p4]] # show the results gp1 = gridplot([select, data_table], ncols=1, plot_width=150, toolbar_options=dict(autohide=True)) gp2 = gridplot([p1, p2, p3, p4], ncols=1, sizing_mode='scale_width', toolbar_location='right') output_file(outputfilename + '.html') show(row(gp1, gp2)) # show(gp2) return True
'Deadlift': 'deadlift', } select = Select(title="Movement", value="Deadlift", options=list(mvmt_name_mapper.keys()), width=200) slider = Slider(start=1, end=10, value=1, step=1, title="Reps", width=200) select.js_on_change( "value", CustomJS(args={ 'p1_cds': cds_pr_cal['Y'][1], 'cds_pr_cal': cds_pr_cal, 'slider': slider, 'mvmt_name_mapper': mvmt_name_mapper }, code=""" const select_value = mvmt_name_mapper[cb_obj.value] p1_cds.data = cds_pr_cal[select_value][slider.value].data p1_cds.change.emit() """)) slider.js_on_change( 'value', CustomJS(args={ 'p1_cds': cds_pr_cal['Y'][1], 'cds_pr_cal': cds_pr_cal, 'select': select, 'mvmt_name_mapper': mvmt_name_mapper },
//Toggle glyph visibility based on checkbox status p0.visible = cb_obj.active.includes(0); p1.visible = cb_obj.active.includes(1); p2.visible = cb_obj.active.includes(2); """) click_reset_tool = CustomJS(args=dict(p=plot), code=""" p.toolbar.tools[""" + util.reset_tool_index(g.TOOLS3) + """].trigger('do'); """) device_slc.on_change('value', device_slc_callback) device_slc.js_on_change( 'value', CustomJS(args=dict(btn=clear_everything_btn), code=""" document.getElementById('modelid_' + btn.id).click(); """)) device_conn_btn.on_click(device_conn_btn_callback) conn_status.js_on_change( 'value', CustomJS(args=dict(btn=device_conn_btn), code=""" console.log('This application is connected to ESP device: ' + cb_obj.value); if(cb_obj.value) { btn.label = "Disconnect from device"; btn.button_type = "warning"; } else {
stock_code_input, stock_name_input, stock_selector ] btngroups = [cp_btnGroup, mb_btnGroup] ssgroups = [stock_code_input, stock_name_input] slidergroups = [mb_slider, cp_slider, date_range_slider] for control in slidergroups: control.callback_policy = 'mouseup' control.callback = query_loading_spinning control.on_change('value', lambda attr, old, new: slider_latency()) for control in ssgroups: control.on_change('value', lambda attr, old, new: update()) control.js_on_change('value', query_loading_spinning) for control in btngroups: control.on_change('active', lambda attr, old, new: update()) control.js_on_change('active', query_loading_spinning) stock_selector.on_change('value', lambda attr, old, new: select_stocks()) stock_selector.js_on_change('value', plot_loading_spinning) update() inputs = Column(*controls, width=320, height=600) inputs.sizing_mode = "fixed" l = layout([[desc], [inputs, p]], sizing_mode="stretch_both") curdoc().add_root(l) curdoc().title = "An Interactive Explorer for Stock Data"
def get_x_eval_selectors_list(result, active_list, x_eval): # Returns a list of selectors. The selectors are sliders for numerical values and dropdown menus # ("Select" object) for categorical values. The selectors are interactive with callbacks everytime # a changed by the user global x_eval_selectors_values bounds = result.space.bounds # Used for defining what values can be selected x_eval_selectors = [] n = 0 # Index of the plots. Example: If only parameter 3 and 5 is being plotted # the selectors for these parameters still have index n = 0 and n= 1. for i in active_list: # Only get selecters that is going to be shown in GUI if isinstance(result.space.dimensions[i], Categorical): # Categorical cats = list(result.space.dimensions[i].categories) # Categories # Create a "Select" object which is a type of dropdown menu # This object gets a title equal to the parameter number, and the value is set to # x_eval select = Select(title='X' + str(i), value=x_eval[i], options=cats, width=200, height=15) # Here we define a callback that updates the appropiate red markers by changing # with the current value of the selector by changing the global "source" variable # The callback function is written in javascript select.js_on_change( 'value', CustomJS(args=dict(source=source, n=n, cats=cats), code=""" // Convert categorical to index var ind = cats.indexOf(cb_obj.value); // Change red line in diagonal plots source['reds'][n][n]['location'] = ind + 0.5; // Change red markers in all contour plots // First we change the plots in a vertical direction for (i = n+1; i < source.reds.length; i++) { source.reds[i][n].data.x = [ind + 0.5] ; source.reds[i][n].change.emit() } // Then in a horizontal direction for (j = 0; j < n; j++) { source.reds[n][j].data.y = [ind + 0.5] ; source.reds[n][j].change.emit(); } """)) x_eval_selectors.append(select) # We update the global selector values x_eval_selectors_values[i] = x_eval[i] else: # Numerical # For numerical values we create a slider # Minimum and maximum values for slider start = bounds[i][0] end = bounds[i][1] # We change the stepsize according to the range of the slider step = get_step_size(start, end) slider = Slider(start=start, end=end, value=x_eval[i], step=step, title='X' + str(i), width=200, height=30) # javascript callback function that gets called everytime a user changes the slider value slider.js_on_change( 'value', CustomJS(args=dict(source=source, n=n), code=""" source.reds[n][n].location = cb_obj.value; source.reds[n][n].change.emit() for (i = n+1; i < source.reds.length; i++) { source.reds[i][n].data.x = [cb_obj.value] ; source.reds[i][n].change.emit(); } for (j = 0; j < n; j++) { source.reds[n][j].data.y = [cb_obj.value] ; source.reds[n][j].change.emit(); } """)) x_eval_selectors.append(slider) x_eval_selectors_values[i] = x_eval[i] n += 1 return x_eval_selectors
p1.legend.location = 'top_left' #Legend(p0) hover1 = p1.select_one(HoverTool) hover1.point_policy = "follow_mouse" hover1.tooltips = [("Category", "@cat"), ("Zone", "@zone")] callback1 = CustomJS(args=dict(source=precip_source), code=""" var data = source.data; var f = cb_obj.value; source.data.cat = data[f]; source.change.emit(); """) select1 = Select(title='Month', value=time_index[-1], options=time_index) select1.js_on_change('value', callback1) #slider = Slider(start=0, end=len(time_index)-1, value=0, step=1) #slider.js_on_change('value', callback) layout1 = column(p1, select1) tab1 = Panel(child=layout1, title='Precip') ## Figure 2 - flow p2 = figure(title='Surface Water Flow Index', tools=TOOLS, logo=None, active_scroll='wheel_zoom', plot_height=h, plot_width=w) p2.patches('x', 'y',
growth_source.change.emit(); """ click_code = """ var condition_ind = growth_source.selected['1d'].indices[0]; console.log(condition_ind); var condition = growth_source.data['condition'][condition_ind] console.log(condition); process_filter.group = selection.value; condition_filter.group = condition; treemap_view.filters = [process_filter, condition_filter]; treemap_source.data.view = treemap_view; treemap_source.change.emit(); """ # Define the callbacks selection_cb = CustomJS(args=args, code=selection_code) click_cb = CustomJS(args=args, code=click_code) # Assign callbacks as necessary selection.js_on_change('value', selection_cb) click_event = growth_plot.select(type=TapTool) click_event.callback = click_cb # Set up the layout row = bokeh.layouts.row(growth_plot, treemap) col = bokeh.layouts.column(selection, row) lay = col bokeh.io.save(lay) # %%
class QCWorkTool: """The almighty QC-tool. Used for quality control of high resolution CTD-data (oceanography). """ # TODO: Well, this is great.. However, we need to simplify and # divide this class into widgets instead.. to be continued.. # - delete color fields? use flag fields instead? def __init__( self, dataframe, datasets=None, settings=None, tabs=None, ctdpy_session=None, export_folder=False, output_filename="CTD_QC_VIZ.html", output_as_notebook=False, output_as_standalone=False, ): """Initiate.""" self.seconds = ColumnDataSource( data=dict(tap_time=[None], reset_time=[None])) self.ctd_session = ctdpy_session self.multi_sensors = settings.multi_sensors self.combo_plots = settings.combo_plots self.map = None self.plot_keys = settings.plot_keys self.datasets = datasets self.key_ds_mapper = self.get_mapper_key_to_ds( settings.file_name_elements) self.parameters = settings.data_parameters_with_units self.plot_parameters_mapping = settings.plot_parameters_mapping self.color_fields = settings.q_colors self.size_fields = settings.scatter_size self.qflag_fields = settings.q_parameters self.auto_qflag_fields = settings.q0_plot_keys self.tabs = tabs self.output_as_notebook = output_as_notebook self.as_standalone = output_as_standalone if self.output_as_notebook: raise NotImplementedError( 'Not yet applicable to work with notebooks!') elif self.as_standalone: output_file(output_filename) self.tile_provider = get_provider(Vendors.CARTODBPOSITRON_RETINA) self.figures = {} xrange_callbacks = {} y_range_setting = None for p in self.plot_parameters_mapping: if p == 'y' or 'q' in p or p[0].isupper() or \ p.startswith('color') or p.startswith('size'): continue param = self.plot_parameters_mapping.get(p) self.figures[p] = figure( tools="pan,reset,wheel_zoom,lasso_select,save", active_drag="lasso_select", title="", height=400, width=400, y_range=y_range_setting, tooltips=[(param, "@{}".format(p)), ("Pressure [dbar]", "@y"), ("Auto-QC", "@{}_q0".format(p))]) self.figures[p].title.align = 'center' self.figures[p].xaxis.axis_label = param self.figures[p].xaxis.axis_label_text_font_style = 'bold' self.figures[p].ygrid.band_fill_alpha = 0.05 self.figures[p].ygrid.band_fill_color = "black" self.figures[p].toolbar.active_scroll = self.figures[p].select_one( WheelZoomTool) if not y_range_setting or (self.multi_sensors and p == 'x4'): self.figures[p].yaxis.axis_label = 'Pressure (dbar)' self.figures[p].yaxis.axis_label_text_font_style = 'bold' y_range_setting = y_range_setting or self.figures[p].y_range xrange_callbacks[p] = cbs.x_range_callback( x_range_obj=self.figures[p].x_range, seconds=self.seconds) self.figures[p].x_range.js_on_change('start', xrange_callbacks[p]) if self.combo_plots and self.multi_sensors: # TODO check the p2 (_) variable.. Should it not be used? for name, p1, _ in zip(('COMBO_TEMP', 'COMBO_SALT', 'COMBO_DOXY'), ('x1', 'x2', 'x3'), ('x4', 'x5', 'x6')): param = self.plot_parameters_mapping.get(p1) self.figures[name] = figure( tools="pan,reset,wheel_zoom,lasso_select,save", active_drag="lasso_select", title="", height=400, width=400, y_range=y_range_setting, ) self.figures[name].title.align = 'center' self.figures[name].xaxis.axis_label = param self.figures[name].xaxis.axis_label_text_font_style = 'bold' self.figures[name].ygrid.band_fill_alpha = 0.05 self.figures[name].ygrid.band_fill_color = "black" self.figures[name].toolbar.active_scroll = \ self.figures[name].select_one(WheelZoomTool) if p1 == 'x1': self.figures[name].yaxis.axis_label = 'Pressure (dbar)' self.figures[ name].yaxis.axis_label_text_font_style = 'bold' cbs.add_hlinked_crosshairs(*(fig_obj for i, fig_obj in self.figures.items())) self.ts = figure( title="CTD TS Diagram", tools=[PanTool(), WheelZoomTool(), ResetTool(), SaveTool()], tooltips=[("Serie", "@key")], height=400, width=400, x_range=(2, 36), y_range=(-2, 20)) self.ts.title.align = 'center' self._setup_position_source(dataframe) self.data_source = setup_data_source( dataframe, pmap=self.plot_parameters_mapping, key_list=np.unique(self.position_source.data['KEY']), parameter_list=self.color_fields + self.size_fields + self.plot_keys + self.auto_qflag_fields + ['COMNT_SAMP'] # noqa: E501 ) self.ts_source = TS_Source() self.ts_source.setup_source(dataframe, self.plot_parameters_mapping) self.ts_plot_source = ColumnDataSource( data=dict(x=[], y=[], color=[], key=[])) self._setup_month_selector() self._setup_comnt_inputs() self._setup_selection_widgets() self._setup_multiflag_widget() self._setup_flag_widgets() self._setup_reset_callback(**xrange_callbacks) self._setup_datasource_callbacks() self._setup_download_button(settings.user_download_directory, export_folder=export_folder, icons=settings.icons) self._setup_get_file_button() self._setup_serie_table() self._setup_info_block(export_folder) self._setup_map() self.ts_axis_ranges = { 't_min': 0, 't_max': 25, 's_min': 2, 's_max': 36 } def get_mapper_key_to_ds(self, file_name_elements): """Return mapper between dataset filename and key. Key = serie key (eg. '20191009_77SE_0005') """ selected_keys = ('SDATE', 'SHIPC', 'SERNO') mapper = {} for ds_name in self.datasets: name_map = { k: v for k, v in zip(file_name_elements, ds_name.replace('.txt', '').split('_')) } mapper['_'.join( (name_map.get(k) for k in selected_keys))] = ds_name return mapper @staticmethod def _get_monthly_keys(position_df): """Return mapper of monthly keys.""" # FIXME Is this really necessary ? dictionary = {'All': position_df['KEY'].to_list()} for month in [str(m).zfill(2) for m in range(1, 13)]: boolean = position_df['MONTH'] == month dictionary[month] = position_df.loc[boolean, 'KEY'].to_list() return dictionary def _setup_position_source(self, df): """Set position data sources. self.position_source: Contains all position information. self.position_plot_source: Contains only the selected information. """ position_df = df[[ 'STATION', 'LATITUDE_DD', 'LONGITUDE_DD', 'KEY', 'MONTH' ]].drop_duplicates(keep='first').reset_index(drop=True) for pos_row in position_df.itertuples(): try: float(pos_row.LATITUDE_DD) except Exception: print('not valid', pos_row.KEY) xs, ys = convert_projection( position_df['LATITUDE_DD'].astype(float).values, position_df['LONGITUDE_DD'].astype(float).values) position_df['LONGI'] = xs position_df['LATIT'] = ys comnts = [] for key in position_df['KEY']: ds_meta = self.datasets[self.key_ds_mapper.get(key)]['metadata'] cv_boolean = ds_meta.str.startswith('//METADATA;COMNT_VISIT;') value = ds_meta[cv_boolean].values[0].replace( '//METADATA;COMNT_VISIT;', '') comnts.append(value) position_df['COMNT_VISIT'] = comnts self.monthly_keys = self._get_monthly_keys(position_df) self.position_source = ColumnDataSource(data=position_df) self.position_plot_source = ColumnDataSource(data=position_df) def _setup_month_selector(self): """Set month selection widget.""" callback = cbs.month_selection_callback( position_source=self.position_source, position_plot_source=self.position_plot_source) self.month_selector = Select( title="Select month", value='All', options=['All'] + pd.date_range( start='2020-01', freq='M', periods=12).month_name().to_list()) self.month_selector.js_on_change('value', callback) # self.month_selector.title.text_align = 'center' callback.args["month"] = self.month_selector def _setup_download_button(self, savepath, export_folder=None, icons=None): """Set download widget.""" self.download_button = cbs.get_download_widget( self.datasets, self.position_plot_source, self.ctd_session, self.key_ds_mapper, savepath, export_folder=export_folder, icons=icons) def _setup_get_file_button(self): """Set file button widget.""" self.file_button = cbs.get_file_widget() def _setup_serie_table(self): """Create data table associated to the position_plot_source object.""" columns = [ TableColumn(field="STATION", title="Station"), TableColumn(field="KEY", title="Key"), ] self.selected_series = DataTable(source=self.position_plot_source, columns=columns, width=300, height=322) def _setup_flag_widgets(self): """Set flag widgets.""" self.flag_widgets = {} for fig_key in self.figures.keys(): if fig_key.startswith('COMBO'): continue parameter = self.plot_parameters_mapping.get(fig_key).split()[0] self.flag_widgets[fig_key] = cbs.get_flag_buttons_widget( self.position_plot_source, self.data_source['main_source'], self.datasets, key_mapper=self.key_ds_mapper, figure_objs=self.figures, flag_keys=self.plot_parameters_mapping[parameter].get( 'q_flags'), color_keys=self.plot_parameters_mapping[parameter].get( 'color_keys'), size_keys=self.plot_parameters_mapping[parameter].get( 'size_keys'), select_button=self.select_all_button) def _setup_comnt_inputs(self): """Set comment input widgets.""" self.comnt_visit = TextInput(value="", title="COMNT_VISIT:") self.comnt_visit_button = cbs.comnt_visit_change_button( datasets=self.datasets, position_source=self.position_plot_source, key_mapper=self.key_ds_mapper, comnt_obj=self.comnt_visit, ) self.comnt_samp = TextInput(value="", title="COMNT_SAMP:") self.comnt_samp_button = cbs.comnt_samp_change_button( datasets=self.datasets, position_source=self.position_plot_source, key_mapper=self.key_ds_mapper, data_source=self.data_source['main_source'], comnt_obj=self.comnt_samp, ) self.comnt_samp_selector = cbs.comnt_samp_selection( data_source=self.data_source['main_source'], comnt_obj=self.comnt_samp, ) def _setup_info_block(self, export_folder): """Set text block objects.""" self.info_block = get_info_block() self.text_export = get_export_info_block(export_folder) self.text_index_selection = standard_block_header( text='Profile index selection', height=30) self.text_multi_serie_flagging = standard_block_header( text='Multi serie parameter flagging', height=30) self.text_meta = standard_block_header(text='Change comments', height=30) self.text_import = standard_block_header(text='Not yet applicable', height=30) def _setup_selection_widgets(self): """Set selection widgets.""" self.select_all_button = cbs.select_button( data_source=self.data_source['main_source']) self.deselect_all_button = cbs.deselect_button( data_source=self.data_source['main_source']) self.pressure_slider = RangeSlider(start=0, end=100, value=(0, 100), step=0.5, title="Select with pressure range", width=300) callback = cbs.range_selection_callback( data_source=self.data_source['main_source']) self.pressure_slider.js_on_change('value', callback) def _setup_multiflag_widget(self): """Set multiflag widgets.""" def sorted_params(plist): para_list = [] i = 0 while i < len(plist): if '2' in plist[i]: para_list.extend([plist[i + 1], plist[i]]) i += 2 else: para_list.append(plist[i]) i += 1 return para_list parameter_list = [] for p in self.figures.keys(): if not p.startswith('COMBO'): parameter_list.append( self.plot_parameters_mapping.get(p).split()[0]) parameter_list = sorted_params(sorted(parameter_list)) self.parameter_selector = Select(title="Select parameter", value=parameter_list[0], options=parameter_list) self.multi_flag_widget = cbs.get_multi_serie_flag_widget( self.position_plot_source, self.data_source, self.datasets, key_mapper=self.key_ds_mapper, parameter_selector=self.parameter_selector, parameter_mapping=self.plot_parameters_mapping, figure_objs=None) def _setup_reset_callback(self, **kwargs): """Set linked figure reset functionality. Autoreset all figures. """ for p in self.figures.keys(): xr_cbs = (xr_cb for xr_cb in kwargs.values()) self.figures[p].js_on_event('reset', cbs.reset_callback(self.seconds), *xr_cbs) def _setup_datasource_callbacks(self): """Set multiflag widgets.""" set_button_type_callback = cbs.change_button_type_callback( button=self.select_all_button, btype='default') self.data_source['main_source'].selected.js_on_change( 'indices', set_button_type_callback) def _setup_map(self): """Initiate the map object including all the connected interactivity.""" pan = PanTool() save = SaveTool() tap = TapTool() lasso = LassoSelectTool() reset = ResetTool() wheel = WheelZoomTool() tooltips = HoverTool(tooltips=[("Station", "@STATION"), ("Serie", "@KEY")]) # range bounds supplied in web mercator coordinates self.map = figure( x_range=(0, 4000000), y_range=(7100000, 9850000), x_axis_type="mercator", y_axis_type="mercator", plot_height=420, plot_width=1000, tools=[pan, wheel, tap, lasso, tooltips, reset, save]) self.map.yaxis.axis_label = ' ' # in order to aline y-axis with figure window below self.map.xgrid.grid_line_color = None self.map.ygrid.grid_line_color = None self.map.toolbar.active_scroll = self.map.select_one(WheelZoomTool) self.map.add_tile(self.tile_provider) station_data_callback = cbs.station_callback( position_source=self.position_plot_source, data_source=self.data_source, figures=self.figures, seconds=self.seconds, pmap=self.plot_parameters_mapping) tap.callback = station_data_callback # When we mark stations on the map using lasso selection, we activate the TS-diagram. lasso_callback = cbs.lasso_callback(monthly_keys=self.monthly_keys, in_data=self.ts_source, plot_data=self.ts_plot_source, x_range=self.ts.x_range, y_range=self.ts.y_range) station_data_callback_2 = cbs.station_callback( position_source=self.position_plot_source, data_source=self.data_source, figures=self.figures, seconds=self.seconds, pmap=self.plot_parameters_mapping) comnt_callback = cbs.comnt_callback( position_source=self.position_plot_source, comnt_obj=self.comnt_visit, single_select=1) comnt_samp_callback = cbs.comnt_samp_callback( position_source=self.position_plot_source, data_source=self.data_source['main_source'], comnt_obj=self.comnt_samp, comnt_selector=self.comnt_samp_selector, single_select=1, ) update_slider_callback = cbs.range_slider_update_callback( slider=self.pressure_slider, data_source=self.data_source['main_source'], ) select_button_type_callback = cbs.change_button_type_callback( button=self.select_all_button, btype='default') lasso_callback.args["month"] = self.month_selector self.position_plot_source.selected.js_on_change( 'indices', lasso_callback, station_data_callback_2, comnt_callback, update_slider_callback, select_button_type_callback, comnt_samp_callback, ) def plot_stations(self): """Plot loaded stations on the map.""" renderer = self.map.circle('LONGI', 'LATIT', source=self.position_plot_source, color="#5BC798", line_color="aquamarine", size=10, alpha=0.7) selected_circle = Circle(fill_alpha=0.5, fill_color="#FF0202", line_color="aquamarine") nonselected_circle = Circle(fill_alpha=0.3, fill_color="#5BC798", line_color="aquamarine") renderer.selection_glyph = selected_circle renderer.nonselection_glyph = nonselected_circle def plot_data(self): """Plot default data in figures. Default data: x=[1] and y=[1]. """ combo_mapping = { 'COMBO_TEMP': ('x1', 'x4'), 'COMBO_SALT': ('x2', 'x5'), 'COMBO_DOXY': ('x3', 'x6') } nonselected_circle = Circle(fill_alpha=0.1, fill_color="#898989", line_color="lightgrey") for p, item in self.figures.items(): if p.startswith('COMBO'): p1, p2 = combo_mapping.get(p) item.line(p1, 'y', color=f"color_{p1}", line_color="navy", line_width=1, alpha=0.3, source=self.data_source['main_source']) item.circle(p1, 'y', color=f"color_{p1}", line_color="white", size=f"size_{p1}", alpha=0.5, source=self.data_source['main_source']) item.line(p2, 'y', color=f"color_{p2}", line_color="navy", line_width=1, alpha=0.3, source=self.data_source['main_source']) item.cross(p2, 'y', color=f"color_{p2}", size=f"size_{p2}", alpha=0.5, source=self.data_source['main_source']) item.y_range.flipped = True else: item.line(p, 'y', color=f"color_{p}", line_color="navy", line_width=1, alpha=0.3, source=self.data_source['main_source']) renderer = item.circle(p, 'y', color=f"color_{p}", line_color="white", size=f"size_{p}", alpha=0.5, source=self.data_source['main_source']) renderer.nonselection_glyph = nonselected_circle item.y_range.flipped = True # T/S - diagram self.ts.circle('x', 'y', color='color', size=3, alpha=0.8, source=self.ts_plot_source, legend_label='Sensor 1') self.ts.toolbar.active_scroll = self.ts.select_one(WheelZoomTool) self.ts.legend.location = "top_left" number_of_colors = int(self.ts_source.data[ self.plot_parameters_mapping.get('y')].max()) * 2 number_of_colors += 1 cm_map = cm.get_cmap('cool', number_of_colors) color_array = [ colors.to_hex(cm_map(c)) for c in range(number_of_colors) ] color_bar = ColorBar( color_mapper=LinearColorMapper( palette=color_array, low=0, high=self.ts_source.data[self.plot_parameters_mapping.get( 'y')].max()), location=(0, 0), ) self.ts.add_layout(color_bar, 'right') x_min, x_max, y_min, y_max = 0, 40, -10, 30 contour_data = get_contour_data(x_min, x_max, y_min, y_max) for key in contour_data.keys(): self.ts.line(contour_data[key]['salt'], contour_data[key]['temp'], line_color="grey", line_alpha=0.8, line_width=1.5) def append_qc_comment(self, meta_series): """Append commnet at the end of the metadata serie. Will be placed on the row just above the data table in each data file. """ time_stamp = get_time_as_format(now=True, fmt='%Y%m%d%H%M') meta_series[len(meta_series) + 1] = '//QC_COMNT; MANUAL QC PERFORMED BY {}; TIMESTAMP {}' \ ''.format(self.ctd_session.settings.user, time_stamp) def get_tab_layout(self): """Return bokeh tab widget.""" fig_tabs = [ Panel(child=column([Spacer(height=30, width=20), self.ts]), title="TS") ] for p, item in self.figures.items(): if (self.multi_sensors and p not in ['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'COMBO_TEMP', 'COMBO_SALT', 'COMBO_DOXY']) \ or (not self.multi_sensors and p not in ['x1', 'x2', 'x3']): tab_layout = column([self.flag_widgets[p], item]) tab_name = self.plot_parameters_mapping.get( p).split()[0].replace('_CTD', '') pan = Panel(child=tab_layout, title=tab_name) fig_tabs.append(pan) return Tabs(tabs=fig_tabs) def get_tabs(self, **kwargs): """Return bokeh tab widget.""" tabs = [] for name, item in kwargs.items(): tab = self.get_column(item) pan = Panel(child=tab, title=name) tabs.append(pan) return Tabs(tabs=tabs) def get_column(self, item): """Return bokeh column layout.""" c_list = [] for attr in item: if type(attr) == str: c_list.append(self.__getattribute__(attr)) elif type(attr) == tuple: r = row([self.__getattribute__(a) for a in attr], sizing_mode="stretch_width") c_list.append(r) return column(c_list) def get_std_parameter_tab_layout(self): """Return list of bokeh column layouts.""" def pan_title(string): return string.split()[0].replace('_CTD', '') columns = [] if self.multi_sensors: for params in zip(('x1', 'x2', 'x3'), ('x4', 'x5', 'x6'), ('COMBO_TEMP', 'COMBO_SALT', 'COMBO_DOXY')): pans = [] for p in params: if p in self.figures: tab_cols = [] if p in self.flag_widgets: tab_cols.append(self.flag_widgets[p]) else: tab_cols.append(Spacer(width=20, height=41)) tab_cols.append(self.figures[p]) tab = column(tab_cols) pan = Panel(child=tab, title=pan_title( self.plot_parameters_mapping.get(p) or p)) pans.append(pan) columns.append(column([Tabs(tabs=pans)])) else: for p1 in ('x1', 'x2', 'x3'): columns.append( column([self.flag_widgets[p1], self.figures[p1]])) return columns def get_layout(self): """Return the complete bokeh layout.""" tabs = self.get_tab_layout() tab_kwargs = { 'Data': [ 'text_index_selection', ('select_all_button', 'deselect_all_button'), 'pressure_slider', 'text_multi_serie_flagging', 'parameter_selector', 'multi_flag_widget' ], 'Metadata': [ 'text_meta', 'comnt_visit', 'comnt_visit_button', 'comnt_samp', 'comnt_samp_selector', 'comnt_samp_button' ], 'Info': ['info_block'] } if not self.as_standalone: tab_kwargs['Import'] = ['text_import', 'file_button'] tab_kwargs['Export'] = ['text_export', 'download_button'] meta_tabs = self.get_tabs(**tab_kwargs) std_parameter_tabs = self.get_std_parameter_tab_layout() widgets_1 = column( [self.month_selector, self.spacer, self.selected_series], sizing_mode="fixed", height=400, width=200) widgets_2 = column([Spacer(height=10, width=125)], sizing_mode="fixed", height=10, width=125) widgets_3 = column([meta_tabs], sizing_mode="stretch_both", height=100, width=100) return grid([ row([self.map, widgets_1, widgets_2, widgets_3]), row([*std_parameter_tabs, column([tabs])]) ]) @property def spacer(self): """Return bokeh spacer.""" return Spacer(height=10, width=20) def return_layout(self): """Return the layout. Can be displayed in an embedded bokeh server. """ return self.get_layout() def show_plot(self): """Show layout in a html-file or in jupyter notebook.""" show(self.get_layout())
TOOLS = "hover,crosshair,pan,wheel_zoom,zoom_in,zoom_out,box_zoom,undo,redo,reset,tap,save,box_select,poly_select,lasso_select" sizing_mode = "fixed" select = Select(title="Sizing mode", value=sizing_mode, options=list(SizingMode)) plot = figure(tools=TOOLS) plot.scatter(x, y, radius=radii, fill_color=colors, fill_alpha=0.6, line_color=None) layout = column(select, plot, sizing_mode=sizing_mode) select.js_on_change( 'value', CustomJS(args=dict(layout=layout, plot=plot), code=""" var sizing_mode = this.value; layout.sizing_mode = sizing_mode; plot.sizing_mode = sizing_mode; """)) output_file("sizing_mode.html", title="sizing_mode.py example") show(layout)
p3.axis.axis_label = None p3.axis.visible = False p3.grid.grid_line_color = None p3.title.text_font_size = '18pt' #######pie ind_hold = 3 hover_callback = CustomJS(args=dict(x=x, source=source, new_data_dict=new_data_dict, inds=inds, title=p3.title, select=select, new_savvy_dict=new_savvy_dict, ind_hold=ind_hold), code=code) select.js_on_change('value', hover_callback) from bokeh.models import FixedTicker, FuncTickFormatter ##hover_callback = CustomJS(args=dict(x=x,new_data_dict=new_data_dict,inds=inds), code = code) ##print('ahsdflasfd') #Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors. Input nan_color. ##color_mapper = LinearColorMapper(palette = palette, low = 0.5, high = 5.5, nan_color = '#d9d9d9') color_mapper = LinearColorMapper(palette=palette, low=0, high=20, nan_color='#d9d9d9') ##color_mapper = LinearColorMapper(palette = [palette[0],palette[-1]], low = 0, high = 25, nan_color = '#d9d9d9') ##LinearColorMapper(palette=Viridis256, low=0, high=100) #Define custom tick labels for color bar.
colors = [ "#%02x%02x%02x" % (int(r), int(g), 150) for r, g in zip(50 + 2 * x, 30 + 2 * y) ] TOOLS = "hover,crosshair,pan,wheel_zoom,zoom_in,zoom_out,box_zoom,undo,redo,reset,tap,save,box_select,poly_select,lasso_select" sizing_mode = "fixed" select = Select(title="Sizing mode", value=sizing_mode, options=list(SizingMode)) plot = figure(tools=TOOLS, sizing_mode=sizing_mode) plot.scatter(x, y, radius=radii, fill_color=colors, fill_alpha=0.6, line_color=None) layout = column(select, plot) layout.sizing_mode = "stretch_both" select.js_on_change( 'value', CustomJS(args=dict(plot=plot), code="plot.sizing_mode = this.value;")) output_file("sizing_mode.html", title="sizing_mode.py example") show(layout)
def bokeh_summary_plot(df, savepath=None): """Summary plot""" from bokeh.plotting import figure from bokeh.layouts import column from bokeh.models import ColumnDataSource, Range1d, HoverTool, TapTool, CustomJS, OpenURL TOOLS = "pan,wheel_zoom,hover,tap,reset,save" colors = get_bokeh_colors() df = df.rename(columns={'level_0': 'predictor'}) df['color'] = [colors[x] for x in df['predictor']] p = figure(title="Summary", tools=TOOLS, width=500, height=500) p.xaxis.axis_label = 'binder_density' p.yaxis.axis_label = 'binders' #make metric for point sizes #df['point_size'] = df.binder_density source = ColumnDataSource(data=df) p.circle(x='binder_density', y='binders', line_color='black', fill_color='color', fill_alpha=0.4, size=10, source=source, legend_group='predictor') hover = p.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ ("name", "@name"), ("length", "@length"), ("binders", "@binders"), ("binder_density", "@binder_density"), ("top_peptide", "@top_peptide"), ("max_score", "@max_score"), ]) p.toolbar.logo = None if savepath != None: url = "http://*****:*****@name" % savepath taptool = p.select(type=TapTool) taptool.callback = OpenURL(url=url) callback = CustomJS(args=dict(source=source), code=""" var data = source.data; var f = cb_obj.value data['x'] = f source.trigger('change'); source.change.emit(); """) from bokeh.layouts import widgetbox from bokeh.models.widgets import Select menu = [(i, i) for i in df.columns] select = Select(title='X', value='A', options=list(df.columns), width=8) select.js_on_change('value', callback) #layout = column(p, select, sizing_mode='scale_width') return p