def interactive_figure(self): """Add interactivity, ie. the option to show/hide lines to the figure.""" lines = self.plot_figure() # Generates a list of lines labels = [line for line in lines.keys()] # Prepare a list of labels for the tickboxes lineNames = ['l'+str(x) for x in range(len(lines))] # Prepare a list of names for the lines lines = {k: v for k, v in zip(lineNames, lines.values())} # Create a dictionary {name: line} activeL = list(range(len(lines))) # List of all line index to mark them as active in CheckboxGroup JScode = [self._visible_line_JS(k) for k in lines] # Generate JavaScript for each line JScode = '\n'.join(JScode) # From a list to a single string with open(osjoin(getcwd(), 'mLearning', 'JScodeAllLines.js'), 'r') as fileJS: buttonJS = fileJS.read() # Read JavaScript code from a file to toggle the visibility of all lines # with open(osjoin(getcwd(), 'mLearning', 'JScode.js'), 'w+') as codeFile: # codeFile.write(JScode) # Write whole CustomJS to a file for debugging purposes callback = CustomJS(code=JScode, args={}) # Args will be added once checkbox and button are added to lines checkbox = CheckboxGroup(labels=labels, active=activeL, # Labels to be ticked from the beginning callback=callback, name='checkbox') # JavaScript var name buttonCallback = CustomJS(code=buttonJS, args={}) # Same as for callback button = Button(label="Select/Unselect All", # Button HTML text button_type="default", callback=buttonCallback, name='button') # JavaScript var name lines['checkbox'], lines['button'] = checkbox, button # Adding widget to lines callback.args, buttonCallback.args = lines, lines # And then lines to callback layout = row(self.fig, widgetbox(children=[button, checkbox], width=200)) # One row, two columns logging.debug('Interaction implemented') return layout
def liability_plot(df_base, df_reform, span, mtr_opt): df_base = ColumnDataSource(df_base) df_reform = ColumnDataSource(df_reform) tools = "pan, zoom_in, zoom_out, reset" fig = figure(plot_width=600, plot_height=500, x_range=(-10000, 300000), y_range=(-20000, 100000), tools=tools, active_drag="pan") fig.yaxis.axis_label = "Tax Liabilities" fig.yaxis.formatter = NumeralTickFormatter(format="$0,000") filer_income = Span(location=span, dimension='height', line_color='black', line_dash='dotted', line_width=1.5) fig.add_layout(filer_income) label_format = f'{span:,}' filer_income_label = Label(x=span, y=25, y_units='screen', x_offset=10, text="{}: $".format(mtr_opt) + label_format, text_color='#303030', text_font="arial", text_font_style="italic", text_font_size="10pt") fig.add_layout(filer_income_label) axis = Span(location=0, dimension='width', line_color='#bfbfbf', line_width=1.5) fig.add_layout(axis) iitax_base = fig.line(x="Axis", y="Individual Income Tax", line_color='#2b83ba', muted_color='#2b83ba', line_width=2, legend="Individual Income Tax Liability", muted_alpha=0.1, source=df_base) payroll_base = fig.line(x="Axis", y="Payroll Tax", line_color='#abdda4', muted_color='#abdda4', line_width=2, legend='Payroll Tax Liability', muted_alpha=0.1, source=df_base) iitax_reform = fig.line(x="Axis", y="Individual Income Tax", line_color='#2b83ba', muted_color='#2b83ba', line_width=2, line_dash='dashed', legend="Individual Income Tax Liability", muted_alpha=0.1, source=df_reform) payroll_reform = fig.line(x="Axis", y="Payroll Tax", line_color='#abdda4', muted_color='#abdda4', line_width=2, line_dash='dashed', legend='Payroll Tax Liability', muted_alpha=0.1, source=df_reform) iitax_base.muted = False payroll_base.muted = False iitax_reform.muted = False payroll_reform.muted = False plot_js = """ object1.visible = toggle.active object2.visible = toggle.active """ base_callback = CustomJS(code=plot_js, args={}) base_toggle = Toggle(label="Base (Solid)", button_type="default", callback=base_callback, active=True) base_callback.args = { "toggle": base_toggle, "object1": iitax_base, "object2": payroll_base } reform_callback = CustomJS(code=plot_js, args={}) reform_toggle = Toggle(label="Reform (Dashed)", button_type="default", callback=reform_callback, active=True) reform_callback.args = { "toggle": reform_toggle, "object1": iitax_reform, "object2": payroll_reform } fig.xaxis.formatter = NumeralTickFormatter(format="$0,000") fig.xaxis.axis_label = mtr_opt fig.xaxis.minor_tick_line_color = None fig.legend.click_policy = "mute" layout = column(fig, row(base_toggle, reform_toggle)) js_liability, div_liability = components(layout) outputs = { "media_type": "bokeh", "title": "Tax Liabilities by {} (Holding Other Inputs Constant)".format( mtr_opt), "data": { "javascript": js_liability, "html": div_liability } } return outputs
def credit_plot(df_base, df_reform, span, mtr_opt): df_base = ColumnDataSource(df_base) df_reform = ColumnDataSource(df_reform) tools = "pan, zoom_in, zoom_out, reset" fig = figure(plot_width=600, plot_height=500, x_range=(-2500, 70000), tools=tools, active_drag="pan") filer_income = Span(location=span, dimension='height', line_color='black', line_dash='dotted', line_width=1.5) fig.add_layout(filer_income) label_format = f'{span:,}' filer_income_label = Label(x=span, y=45, y_units='screen', x_offset=10, text="{}: $".format(mtr_opt) + label_format, text_color='#303030', text_font="arial", text_font_style="italic", text_font_size="10pt") fig.add_layout(filer_income_label) axis = Span(location=0, dimension='width', line_color='#bfbfbf', line_width=1.5) fig.add_layout(axis) eitc_base = fig.line(x="Axis", y="EITC", line_color='#2b83ba', muted_color='#2b83ba', line_width=2, legend="Earned Income Tax Credit", muted_alpha=0.1, source=df_base) ctc_base = fig.line(x="Axis", y="CTC", line_color='#abdda4', muted_color='#abdda4', line_width=2, legend='Nonrefundable Child Tax Credit', muted_alpha=0.1, source=df_base) ctc_refund_base = fig.line(x="Axis", y="CTC Refundable", line_color='#fdae61', muted_color='#fdae61', line_width=2, legend='Refundable Child Tax Credit', muted_alpha=0.1, source=df_base) cdcc_base = fig.line(x="Axis", y="Child care credit", line_color='#d7191c', muted_color='#d7191c', line_width=2, legend='Child and Dependent Care Credit', muted_alpha=0.1, source=df_base) eitc_reform = fig.line(x="Axis", y="EITC", line_color='#2b83ba', muted_color='#2b83ba', line_width=2, line_dash='dashed', legend="Earned Income Tax Credit", muted_alpha=0.1, source=df_reform) ctc_reform = fig.line(x="Axis", y="CTC", line_color='#abdda4', muted_color='#abdda4', line_width=2, line_dash='dashed', legend='Nonrefundable Child Tax Credit', muted_alpha=0.1, source=df_reform) ctc_refund_reform = fig.line(x="Axis", y="CTC Refundable", line_color='#fdae61', muted_color='#fdae61', line_width=2, line_dash='dashed', legend='Refundable Child Tax Credit', muted_alpha=0.1, source=df_reform) cdcc_reform = fig.line(x="Axis", y="Child care credit", line_color='#d7191c', muted_color='#d7191c', line_width=2, line_dash='dashed', legend='Child and Dependent Care Credit', muted_alpha=0.1, source=df_reform) ctc_base.muted = True ctc_refund_base.muted = True cdcc_base.muted = True ctc_reform.muted = True ctc_refund_reform.muted = True cdcc_reform.muted = True plot_js = """ object1.visible = toggle.active object2.visible = toggle.active object3.visible = toggle.active object4.visible = toggle.active """ base_callback = CustomJS(code=plot_js, args={}) base_toggle = Toggle(label="Base (Solid)", button_type="default", callback=base_callback, active=True) base_callback.args = { "toggle": base_toggle, "object1": eitc_base, "object2": cdcc_base, "object3": ctc_base, "object4": ctc_refund_base } reform_callback = CustomJS(code=plot_js, args={}) reform_toggle = Toggle(label="Reform (Dashed)", button_type="default", callback=reform_callback, active=True) reform_callback.args = { "toggle": reform_toggle, "object1": eitc_reform, "object2": cdcc_reform, "object3": ctc_reform, "object4": ctc_refund_reform } fig.yaxis.formatter = NumeralTickFormatter(format="$0,000") fig.yaxis.axis_label = "Tax Credits" fig.xaxis.formatter = NumeralTickFormatter(format="$0,000") fig.xaxis.axis_label = mtr_opt fig.xaxis.minor_tick_line_color = None fig.legend.click_policy = "mute" layout = column(fig, row(base_toggle, reform_toggle)) js_credit, div_credit = components(layout) outputs = { "media_type": "bokeh", "title": "Tax Credits by {} (Holding Other Inputs Constant)".format(mtr_opt), "data": { "javascript": js_credit, "html": div_credit } } return outputs
def liability_plot(df_base, df_reform): df_base = ColumnDataSource(df_base) df_reform = ColumnDataSource(df_reform) fig = figure(plot_width=600, plot_height=500, x_range=(0, 300000), y_range=(-20000, 100000)) fig.yaxis.axis_label = "Tax Liabilities" fig.yaxis.formatter = NumeralTickFormatter(format="$0,000") iitax_base = fig.line(x="Wages", y="Individual Income Tax", line_color='#2b83ba', muted_color='#2b83ba', line_width=2, legend="Individual Income Tax Liability", muted_alpha=0.1, source=df_base) payroll_base = fig.line(x="Wages", y="Payroll Tax", line_color='#abdda4', muted_color='#abdda4', line_width=2, legend='Payroll Tax Liability', muted_alpha=0.1, source=df_base) iitax_reform = fig.line(x="Wages", y="Individual Income Tax", line_color='#2b83ba', muted_color='#2b83ba', line_width=2, line_dash='dashed', legend="Individual Income Tax Liability", muted_alpha=0.1, source=df_reform) payroll_reform = fig.line(x="Wages", y="Payroll Tax", line_color='#abdda4', muted_color='#abdda4', line_width=2, line_dash='dashed', legend='Payroll Tax Liability', muted_alpha=0.1, source=df_reform) iitax_base.muted = False payroll_base.muted = False iitax_reform.muted = False payroll_reform.muted = False plot_js = """ object1.visible = toggle.active object2.visible = toggle.active """ base_callback = CustomJS(code=plot_js, args={}) base_toggle = Toggle(label="Base (Solid)", button_type="default", callback=base_callback, active=True) base_callback.args = { "toggle": base_toggle, "object1": iitax_base, "object2": payroll_base } reform_callback = CustomJS(code=plot_js, args={}) reform_toggle = Toggle(label="Reform (Dashed)", button_type="default", callback=reform_callback, active=True) reform_callback.args = { "toggle": reform_toggle, "object1": iitax_reform, "object2": payroll_reform } fig.xaxis.formatter = NumeralTickFormatter(format="$0,000") fig.xaxis.axis_label = "Household Wages" fig.xaxis.minor_tick_line_color = None fig.legend.click_policy = "mute" layout = column(fig, row(base_toggle, reform_toggle)) js_liability, div_liability = components(layout) outputs = { "media_type": "bokeh", "title": "Tax Liabilities by Wage (Holding Other Inputs Constant)", "data": { "javascript": js_liability, "html": div_liability } } return outputs
def credit_plot(df_base, df_reform): df_base = ColumnDataSource(df_base) df_reform = ColumnDataSource(df_reform) fig = figure(plot_width=600, plot_height=500, x_range=(0, 70000)) eitc_base = fig.line(x="Wages", y="EITC", line_color='#2b83ba', muted_color='#2b83ba', line_width=2, legend="Earned Income Tax Credit", muted_alpha=0.1, source=df_base) ctc_base = fig.line(x="Wages", y="CTC", line_color='#abdda4', muted_color='#abdda4', line_width=2, legend='Nonrefundable Child Tax Credit', muted_alpha=0.1, source=df_base) ctc_refund_base = fig.line(x="Wages", y="CTC Refundable", line_color='#fdae61', muted_color='#fdae61', line_width=2, legend='Refundable Child Tax Credit', muted_alpha=0.1, source=df_base) cdcc_base = fig.line(x="Wages", y="Child care credit", line_color='#d7191c', muted_color='#d7191c', line_width=2, legend='Child and Dependent Care Credit', muted_alpha=0.1, source=df_base) eitc_reform = fig.line(x="Wages", y="EITC", line_color='#2b83ba', muted_color='#2b83ba', line_width=2, line_dash='dashed', legend="Earned Income Tax Credit", muted_alpha=0.1, source=df_reform) ctc_reform = fig.line(x="Wages", y="CTC", line_color='#abdda4', muted_color='#abdda4', line_width=2, line_dash='dashed', legend='Nonrefundable Child Tax Credit', muted_alpha=0.1, source=df_reform) ctc_refund_reform = fig.line(x="Wages", y="CTC Refundable", line_color='#fdae61', muted_color='#fdae61', line_width=2, line_dash='dashed', legend='Refundable Child Tax Credit', muted_alpha=0.1, source=df_reform) cdcc_reform = fig.line(x="Wages", y="Child care credit", line_color='#d7191c', muted_color='#d7191c', line_width=2, line_dash='dashed', legend='Child and Dependent Care Credit', muted_alpha=0.1, source=df_reform) ctc_base.muted = True ctc_refund_base.muted = True cdcc_base.muted = True ctc_reform.muted = True ctc_refund_reform.muted = True cdcc_reform.muted = True plot_js = """ object1.visible = toggle.active object2.visible = toggle.active object3.visible = toggle.active object4.visible = toggle.active """ base_callback = CustomJS(code=plot_js, args={}) base_toggle = Toggle(label="Base (Solid)", button_type="default", callback=base_callback, active=True) base_callback.args = { "toggle": base_toggle, "object1": eitc_base, "object2": cdcc_base, "object3": ctc_base, "object4": ctc_refund_base } reform_callback = CustomJS(code=plot_js, args={}) reform_toggle = Toggle(label="Reform (Dashed)", button_type="default", callback=reform_callback, active=True) reform_callback.args = { "toggle": reform_toggle, "object1": eitc_reform, "object2": cdcc_reform, "object3": ctc_reform, "object4": ctc_refund_reform } fig.yaxis.formatter = NumeralTickFormatter(format="$0,000") fig.yaxis.axis_label = "Tax Credits" fig.xaxis.formatter = NumeralTickFormatter(format="$0,000") fig.xaxis.axis_label = "Household Wages" fig.xaxis.minor_tick_line_color = None fig.legend.click_policy = "mute" layout = column(fig, row(base_toggle, reform_toggle)) js_credit, div_credit = components(layout) outputs = { "media_type": "bokeh", "title": "Tax Credits by Wage (Holding Other Inputs Constant)", "data": { "javascript": js_credit, "html": div_credit } } return outputs
from bokeh.io import output_file, show from bokeh.plotting import figure from bokeh.layouts import layout from bokeh.models import Toggle, BoxAnnotation, CustomJS # We set-up the same standard figure with two lines and now a box over top p = figure(plot_width=600, plot_height=200, tools='') visible_line = p.line([1, 2, 3], [1, 2, 1], line_color="blue") invisible_line = p.line([1, 2, 3], [2, 1, 2], line_color="pink") box = BoxAnnotation(left=1.5, right=2.5, fill_color='green', fill_alpha=0.1) p.add_layout(box) # We write JavaScript to link toggle with visible property of box and line code = '''\ object.visible = toggle.active ''' callback1 = CustomJS(code=code, args={}) toggle1 = Toggle(label="Green Box", button_type="success", callback=callback1) callback1.args = {'toggle': toggle1, 'object': box} callback2 = CustomJS(code=code, args={}) toggle2 = Toggle(label="Pink Line", button_type="success", callback=callback2) callback2.args = {'toggle': toggle2, 'object': invisible_line} output_file("styling_visible_annotation_with_interaction.html") show(layout([p], [toggle1, toggle2]))
def rate_plot(df_base, df_reform, span, mtr_opt): df_base = ColumnDataSource(df_base) df_reform = ColumnDataSource(df_reform) tools = "pan, zoom_in, zoom_out, reset" fig = figure(plot_width=600, plot_height=500, x_range=(-10000, 300000), y_range=(-0.3, 0.5), tools=tools, active_drag="pan") fig.yaxis.axis_label = "Tax Rate" fig.yaxis.formatter = NumeralTickFormatter(format="0%") filer_income = Span(location=span, dimension='height', line_color='black', line_dash='dotted', line_width=1.5) fig.add_layout(filer_income) label_format = f'{span:,}' filer_income_label = Label(x=span, y=25, y_units='screen', x_offset=10, text="{}: $".format(mtr_opt) + label_format, text_color='#303030', text_font="arial", text_font_style="italic", text_font_size="10pt") fig.add_layout(filer_income_label) axis = Span(location=0, dimension='width', line_color='#bfbfbf', line_width=1.5) fig.add_layout(axis) iitax_atr_base = fig.line(x="Axis", y="IATR", line_color='#2b83ba', muted_color='#2b83ba', line_width=2, legend_label="Income Tax Average Rate", muted_alpha=0.1, source=df_base) payroll_atr_base = fig.line(x="Axis", y="PATR", line_color='#abdda4', muted_color='#abdda4', line_width=2, legend_label='Payroll Tax Average Rate', muted_alpha=0.1, source=df_base) iitax_mtr_base = fig.line(x="Axis", y="Income Tax MTR", line_color='#fdae61', muted_color='#fdae61', line_width=2, legend_label="Income Tax Marginal Rate", muted_alpha=0.1, source=df_base) payroll_mtr_base = fig.line(x="Axis", y="Payroll Tax MTR", line_color='#d7191c', muted_color='#d7191c', line_width=2, legend_label='Payroll Tax Marginal Rate', muted_alpha=0.1, source=df_base) iitax_atr_reform = fig.line(x="Axis", y="IATR", line_color='#2b83ba', muted_color='#2b83ba', line_width=2, line_dash='dashed', legend_label="Income Tax Average Rate", muted_alpha=0.1, source=df_reform) payroll_atr_reform = fig.line(x="Axis", y="PATR", line_color='#abdda4', muted_color='#abdda4', line_width=2, line_dash='dashed', legend_label='Payroll Tax Average Rate', muted_alpha=0.1, source=df_reform) iitax_mtr_reform = fig.line(x="Axis", y="Income Tax MTR", line_color='#fdae61', muted_color='#fdae61', line_width=2, line_dash='dashed', legend_label="Income Tax Marginal Rate", muted_alpha=0.1, source=df_reform) payroll_mtr_reform = fig.line(x="Axis", y="Payroll Tax MTR", line_color='#d7191c', muted_color='#d7191c', line_width=2, line_dash='dashed', legend_label='Payroll Tax Marginal Rate', muted_alpha=0.1, source=df_reform) iitax_atr_base.muted = False iitax_mtr_base.muted = True payroll_atr_base.muted = True payroll_mtr_base.muted = True iitax_atr_reform.muted = False iitax_mtr_reform.muted = True payroll_atr_reform.muted = True payroll_mtr_reform.muted = True plot_js = """ object1.visible = toggle.active object2.visible = toggle.active object3.visible = toggle.active object4.visible = toggle.active """ base_callback = CustomJS(code=plot_js, args={}) base_toggle = Toggle(label="Base (Solid)", button_type="default", active=True) base_callback.args = { "toggle": base_toggle, "object1": iitax_atr_base, "object2": payroll_atr_base, "object3": iitax_mtr_base, "object4": payroll_mtr_base } base_toggle.js_on_change('active', base_callback) reform_callback = CustomJS(code=plot_js, args={}) reform_toggle = Toggle(label="Reform (Dashed)", button_type="default", active=True) reform_callback.args = { "toggle": reform_toggle, "object1": iitax_atr_reform, "object2": payroll_atr_reform, "object3": iitax_mtr_reform, "object4": payroll_mtr_reform } reform_toggle.js_on_change('active', reform_callback) fig.xaxis.formatter = NumeralTickFormatter(format="$0,000") fig.xaxis.axis_label = mtr_opt fig.xaxis.minor_tick_line_color = None fig.legend.click_policy = "mute" layout = column(fig, row(base_toggle, reform_toggle)) data = json_item(layout) outputs = { "media_type": "bokeh", "title": "Tax Rates by {} (Holding Other Inputs Constant)".format(mtr_opt), "data": data } return outputs
code = """ if (0 in checkbox.active) { l0.visible = true } else { l0.visible = false } if (1 in checkbox.active) { l1.visible = true } else { l1.visible = false } if (2 in checkbox.active) { l2.visible = true } else { l2.visible = false } """ p = figure() props = dict(line_width=4, line_alpha=0.7) x = np.linspace(0, 4 * np.pi, 100) l0 = p.line(x, np.sin(x), color=Viridis3[0], legend="Line 0", **props) l1 = p.line(x, 4 * np.cos(x), color=Viridis3[1], legend="Line 1", **props) l2 = p.line(x, np.tan(x), color=Viridis3[2], legend="Line 2", **props) callback = CustomJS(code=code, args={}) checkbox = CheckboxGroup(labels=["Line 0", "Line 1", "Line 2"], active=[0, 1, 2], callback=callback, width=100) callback.args = dict(l0=l0, l1=l1, l2=l2, checkbox=checkbox) layout = row(checkbox, p) show(layout)
callback_policy="mouseup") callback = CustomJS(code=code, args={}) checkbox = CheckboxGroup(labels=[ "Quantum", "Seismic", "Newtonian", "Suspension thermal", "Coating Brownian", "Coating thermo-optic", "Substrate Brownian", "Substrate thermo-elastic", "Excess gas" ], active=[0, 1, 2, 3, 4], callback=callback) callback.args = dict(l_qua=l_qua, l_sei=l_sei, l_new=l_new, l_sth=l_sth, l_cbr=l_cbr, l_cto=l_cto, l_sbr=l_sbr, l_ste=l_ste, l_exg=l_exg, checkbox=checkbox) def totalnoise_handler(self): if (l_tot.visible == True): l_tot.visible = False else: l_tot.visible = True def totalnoise_handler_aL(self): if (l_aL.visible == True):
legend=location, y_range_name='humidity', line_dash="dashed", ) plot_locations.update({location+"_t": t, location+"_rh": rh}) code = "console.log('value: ' + multiselect.attributes.value);\n " + "console.log('value_type: ' + Object.prototype.toString.call(multiselect.attributes.value).slice(8, -1));\n " + "console.log('options: ' + multiselect.attributes.options);\n " + "".join(generate_selector_code(data_per_loc.keys())) return p, code, plot_locations output_file("c:\html\multiselect_val.html") p, code, plot_locations = generate_plot(data_per_loc) ms_options = [(str(i), v) for i , v in enumerate(locations)] ms_value = [str(i) for i in range(len(locations))] callback = CustomJS(code=code, args={}) multiselect = MultiSelect(title="Location:", options=ms_options value=ms_value, callback=callback) callback.args = dict(**plot_locations, multiselect=multiselect) layout = row(p, multiselect) show(layout) output_file("c:\html\multiselect_loc.html") p, code, plot_locations = generate_plot(data_per_loc) ms_options = locations ms_value = locations callback = CustomJS(code=code, args={}) multiselect = MultiSelect(title="Location:", options=ms_options, value=ms_value, callback=callback) callback.args = dict(**plot_locations, multiselect=multiselect)
def bokeh_plot(node, link, name='NetworkMap'): from bokeh.plotting import figure, from_networkx, save from bokeh.models import ColumnDataSource, HoverTool from bokeh.io import export_png from bokeh.models import CustomJS, TextInput, CustomJSFilter, CDSView, TapTool from bokeh.layouts import column from bokeh.plotting import output_file, show from bokeh.tile_providers import get_provider, Vendors from bokeh.models import Circle, MultiLine, LabelSet, Toggle, CheckboxGroup from bokeh.models.graphs import NodesAndLinkedEdges text_input = TextInput(value="", title="Filter Nodes:") wgs84_to_web_mercator(node) node_source_data = ColumnDataSource( data=dict(x=node['MX'], y=node['MY'], desc=node['id'])) # link G = nx.from_pandas_edgelist(link, source='id', target='anode') nx.set_node_attributes(G, dict(zip(link.id, link.id)), 'desc') n_loc = {k: (x, y) for k, x, y in zip(node['id'], node['MX'], node['MY'])} nx.set_node_attributes(G, n_loc, 'pos') n_color = {k: 'orange' if 'C' in k else 'green' for k in node['id']} nx.set_node_attributes(G, n_color, 'color') n_alpha = {k: 1 if 'C' in k else 0 for k in node['id']} nx.set_node_attributes(G, n_alpha, 'alpha') e_color = {(s, t): 'red' if 'C' in s else 'black' for s, t in zip(link['id'], link['anode'])} nx.set_edge_attributes(G, e_color, 'color') e_line_type = {(s, t): 'dashed' if 'C' in s else 'solid' for s, t in zip(link['id'], link['anode'])} nx.set_edge_attributes(G, e_line_type, 'line_type') tile_provider = get_provider(Vendors.CARTODBPOSITRON) bokeh_plot = figure(title="%s network map" % name.split('/')[-1].split('.')[0], sizing_mode="scale_height", plot_width=1300, x_range=(min(node['MX']), max(node['MX'])), tools='pan,wheel_zoom', active_drag="pan", active_scroll="wheel_zoom") bokeh_plot.add_tile(tile_provider) # This callback is crucial, otherwise the filter will not be triggered when the slider changes callback = CustomJS(args=dict(source=node_source_data), code=""" source.change.emit(); """) text_input.js_on_change('value', callback) # Define the custom filter to return the indices from 0 to the desired percentage of total data rows. You could # also compare against values in source.data js_filter = CustomJSFilter(args=dict(text_input=text_input), code=f""" const z = source.data['desc']; var indices = ((() => {{ var result = []; for (let i = 0, end = source.get_length(), asc = 0 <= end; asc ? i < end : i > end; asc ? i++ : i--) {{ if (z[i].includes(text_input.value.toString(10))) {{ result.push(i); }} }} return result; }})()); return indices;""") # Use the filter in a view view = CDSView(source=node_source_data, filters=[js_filter]) callback2 = CustomJS(args=dict(x_range=bokeh_plot.x_range, y_range=bokeh_plot.y_range, text_input=text_input, source=node_source_data), code=f""" const z = source.data['desc']; const x = source.data['x']; const y = source.data['y']; var result = []; for (let i = 0, end = source.get_length(), asc = 0 <= end; asc ? i < end : i > end; asc ? i++ : i--) {{ if (z[i].includes(text_input.value.toString(10))) {{ result.push(i); }} }} var indices = result[0]; var Xstart = x[indices]; var Ystart = y[indices]; y_range.setv({{"start": Ystart-280, "end": Ystart+280}}); x_range.setv({{"start": Xstart-500, "end": Xstart+500}}); x_range.change.emit(); y_range.change.emit(); """) text_input.js_on_change('value', callback2) graph = from_networkx(G, nx.get_node_attributes(G, 'pos'), scale=2, center=(0, 0)) graph.node_renderer.glyph = Circle(radius=15, fill_color='color', fill_alpha='alpha') graph.node_renderer.hover_glyph = Circle(radius=15, fill_color='red') graph.edge_renderer.glyph = MultiLine( line_alpha=1, line_color='color', line_width=1, line_dash='line_type') # zero line alpha graph.edge_renderer.hover_glyph = MultiLine(line_color='#abdda4', line_width=5) graph.inspection_policy = NodesAndLinkedEdges() bokeh_plot.circle('x', 'y', source=node_source_data, radius=10, color='green', alpha=0.7, view=view) labels = LabelSet(x='x', y='y', text='desc', text_font_size="8pt", text_color='black', x_offset=5, y_offset=5, source=node_source_data, render_mode='canvas') code = '''\ if (toggle.active) { box.text_alpha = 0.0; console.log('enabling box'); } else { box.text_alpha = 1.0; console.log('disabling box'); } ''' callback3 = CustomJS(code=code, args={}) toggle = Toggle(label="Annotation", button_type="success") toggle.js_on_click(callback3) callback3.args = {'toggle': toggle, 'box': labels} bokeh_plot.add_tools(HoverTool(tooltips=[("id", "@desc")]), TapTool()) # Output filepath bokeh_plot.renderers.append(graph) bokeh_plot.add_layout(labels) layout = column(toggle, text_input, bokeh_plot) # export_png(p, filename="plot.png") output_file(name) show(layout)
def aggregate_plot(tb): """ Function for creating a bokeh plot that shows aggregate tax liabilities for each year the TaxBrain instance was run Parameters ---------- tb: An instance of the TaxBrain object Returns ------- Bokeh figure """ # Pull aggregate data by year and transpose it for plotting varlist = ["iitax", "payrolltax", "combined"] base_data = tb.multi_var_table(varlist, "base").transpose() base_data["calc"] = "Base" reform_data = tb.multi_var_table(varlist, "reform").transpose() reform_data["calc"] = "Reform" base_cds = ColumnDataSource(base_data) reform_cds = ColumnDataSource(reform_data) num_ticks = len(base_data) del base_data, reform_data fig = figure(title="Aggregate Tax Liability by Year", width=700, height=500, tools="save") ii_base = fig.line(x="index", y="iitax", line_width=4, line_color="#12719e", legend_label="Income Tax - Base", source=base_cds) ii_reform = fig.line(x="index", y="iitax", line_width=4, line_color="#73bfe2", legend_label="Income Tax - Reform", source=reform_cds) proll_base = fig.line(x="index", y="payrolltax", line_width=4, line_color="#408941", legend_label="Payroll Tax - Base", source=base_cds) proll_reform = fig.line(x="index", y="payrolltax", line_width=4, line_color="#98cf90", legend_label="Payroll Tax - Reform", source=reform_cds) comb_base = fig.line(x="index", y="combined", line_width=4, line_color="#a4201d", legend_label="Combined - Base", source=base_cds) comb_reform = fig.line(x="index", y="combined", line_width=4, line_color="#e9807d", legend_label="Combined - Reform", source=reform_cds) # format figure fig.legend.location = "top_left" fig.yaxis.formatter = NumeralTickFormatter(format="$0.00a") fig.yaxis.axis_label = "Aggregate Tax Liability" fig.xaxis.minor_tick_line_color = None fig.xaxis[0].ticker.desired_num_ticks = num_ticks # Add hover tool tool_str = """ <p><b>@calc - {}</b></p> <p>${}</p> """ ii_hover = HoverTool(tooltips=tool_str.format("Individual Income Tax", "@iitax{0,0}"), renderers=[ii_base, ii_reform]) proll_hover = HoverTool(tooltips=tool_str.format("Payroll Tax", "@payrolltax{0,0}"), renderers=[proll_base, proll_reform]) combined_hover = HoverTool(tooltips=tool_str.format( "Combined Tax", "@combined{0,0}"), renderers=[comb_base, comb_reform]) fig.add_tools(ii_hover, proll_hover, combined_hover) # toggle which lines are shown plot_js = """ object1.visible = toggle.active object2.visible = toggle.active object3.visible = toggle.active """ base_callback = CustomJS(code=plot_js, args={}) base_toggle = Toggle(label="Base", button_type="primary", active=True) base_callback.args = { "toggle": base_toggle, "object1": ii_base, "object2": proll_base, "object3": comb_base } base_toggle.js_on_change('active', base_callback) reform_callback = CustomJS(code=plot_js, args={}) reform_toggle = Toggle(label="Reform", button_type="primary", active=True) reform_callback.args = { "toggle": reform_toggle, "object1": ii_reform, "object2": proll_reform, "object3": comb_reform } fig_layout = layout([fig], [base_toggle, reform_toggle]) reform_toggle.js_on_change('active', reform_callback) # Components needed to embed the figure data = json_item(fig_layout) outputs = { "media_type": "bokeh", "title": "", "data": data, } return outputs
if (0 in checkbox.active) { l0.visible = true } else { l0.visible = false } if (1 in checkbox.active) { l1.visible = true } else { l1.visible = false } if (2 in checkbox.active) { l2.visible = true } else { l2.visible = false } """ p = figure() props = dict(line_width=4, line_alpha=0.7) x = np.linspace(0, 4 * np.pi, 100) l0 = p.line(x, np.sin(x), color=Viridis3[0], legend="Line 0", **props) l1 = p.line(x, 4 * np.cos(x), color=Viridis3[1], legend="Line 1", **props) l2 = p.line(x, np.tan(x), color=Viridis3[2], legend="Line 2", **props) callback = CustomJS(code=code, args={}) checkbox = CheckboxGroup(labels=["Line 0", "Line 1", "Line 2"], active=[0, 1, 2], callback=callback, width=100) callback.args = dict(l0=l0, l1=l1, l2=l2, checkbox=checkbox) layout = row(checkbox, p) show(layout)