def champion_count_placement(self, champion_count_placement_df): output_file( f"assets/plot/{self.file_name_prefix}/unit_count_placement_plot.html" ) # Sort dataframe by cost champion_count_placement_df = champion_count_placement_df.sort_values( by=['count']) # Plot with all units panels = [] fig, background_image = champion_count_placement.build_plot( champion_count_placement_df, theme=unit_stacked_bar_theme) panels += [ Panel(child=Row(fig, background_image), title='All Champions') ] # Plot by cost of units units_df_by_cost = split_df_by_champion_cost( set_name='set3', df=champion_count_placement_df) for index, df_data in enumerate(units_df_by_cost.values()): cost_unit_df = pd.DataFrame( df_data, columns=champion_count_placement_df.columns) fig, background_image = champion_count_placement.build_plot( cost_unit_df, theme=unit_stacked_bar_theme) panels += [ Panel(child=Row(fig, background_image), title=f'{index+1} Cost Champions') ] tabs = Tabs(tabs=panels) save(tabs)
def test_visit_immediate_value_references() -> None: r1 = LayoutDOM() r2 = LayoutDOM() row = Row(children=[LayoutDOM()]) obj = Row(children=[r1, r2, row]) vals = set() assert bmu.visit_immediate_value_references(obj, lambda x: vals.add(x)) is None assert vals == {r1, r2, row}
def test_collect_models() -> None: r1 = LayoutDOM() r2 = LayoutDOM() r3 = LayoutDOM() row1 = Row(children=[r1, r2]) row2 = Row(children=[r2, r3]) models = bmu.collect_models(row1, row2) assert len(models) == 5 assert set(models) == {r1, r2, r3, row1, row2}
def test_prop_defaults(self) -> None: from bokeh.models import Panel, Row child1 = Row() child2 = Row() p1 = Panel(child=child1) p2 = Panel(child=child2) assert p1.title == "" assert p2.title == "" assert p1.child == child1 assert p2.child == child2
def test_Model(self) -> None: r1 = LayoutDOM() r2 = LayoutDOM() r3 = LayoutDOM() row = Row(children=[r3]) obj = Row(children=[r1, r2, row]) vals = set() assert bmu.visit_value_and_its_immediate_references( obj, lambda x: vals.add(x)) is None assert vals == {obj}
def handle_selected_graph(selected): logger.info("handle selected graph. selected = %s", str(selected)) label.text = "Please Wait..." global apply_filter if top_before is not None: if apply_filter: regenerate_graphs(int(top_n_dropdown.value), int(top_n_clusters_dropdown.value)) apply_filter = False if selected == 0: if trend_clustering is None: graphs_area.children = [ Row(top_before, top_after), Row(hot_trends, cold_trends), Row(custom_trends) ] else: graphs_area.children = [ Row(top_before, top_after), Row(hot_trends, cold_trends), Row(trend_clustering, custom_trends), Row(topic_clustering_before, topic_clustering_after) ] if selected == 1: graphs_area.children = [Row(top_before, top_after)] if selected == 2: graphs_area.children = [Row(hot_trends, cold_trends)] if selected == 3: if trend_clustering is None: graphs_area.children = [Div(text='no word embedding data')] else: graphs_area.children = [trend_clustering] if selected == 4: graphs_area.children = [custom_trends] if selected == 5: if topic_clustering_before is None: graphs_area.children = [Div(text='no word embedding data')] else: graphs_area.children = [ Row(topic_clustering_before, topic_clustering_after) ] if selected == 6: filter_topics_table_source.data = {'topics': filter_rows} filter_topics_table_source.selected.indices = get_valid_indices() filter_custom_table_source.data = {'topics': filter_rows} filter_custom_table_source.selected.indices = get_custom_indices() refresh_filter_area() apply_filter = False label.text = ""
def circuit_from(bqm): G = bqm.to_networkx_graph() plot = Plot( plot_width=600, plot_height=400, x_range=Range1d(-0.1, 1.1), y_range=Range1d(-0.1, 1.1) ) plot.title.text = "Multiplication as a BQM" plot.add_tools(HoverTool(tooltips=None), TapTool(), BoxSelectTool()) graph_renderer = from_networkx(G, circuit_layout) circle_size = 25 graph_renderer.node_renderer.glyph = Circle(size=circle_size, fill_color="#F5F7FB") graph_renderer.node_renderer.selection_glyph = Circle(size=circle_size, fill_color="#EEA64E") graph_renderer.node_renderer.hover_glyph = Circle(size=circle_size, fill_color="#FFE86C") edge_size = 2 graph_renderer.edge_renderer.glyph = MultiLine( line_color="#CCCCCC", line_alpha=0.8, line_width=edge_size ) graph_renderer.edge_renderer.selection_glyph = MultiLine( line_color="#EEA64E", line_width=edge_size ) graph_renderer.edge_renderer.hover_glyph = MultiLine(line_color="#FFE86C", line_width=edge_size) graph_renderer.selection_policy = NodesAndLinkedEdges() graph_renderer.inspection_policy = NodesAndLinkedEdges() plot.renderers.append(graph_renderer) plot.background_fill_color = "#202239" add_labels(plot) show(Row(plot))
def color_picker(): def color_slider(title, color): return Slider(title=title, show_value=False, value=127, start=0, end=255, step=1, orientation="vertical", bar_color=color) red = color_slider("R", "red") green = color_slider("G", "green") blue = color_slider("B", "blue") div = Div(width=100, height=100, background="rgb(127, 127, 127)") cb = CustomJS(args=dict(red=red, green=green, blue=blue, div=div), code=""" const r = red.value const g = green.value const b = blue.value div.background = `rgb(${r}, ${g}, ${b})` """) red.js_on_change('value', cb) green.js_on_change('value', cb) blue.js_on_change('value', cb) return Row(children=[red, green, blue, div])
def _redraw_conditions(self): self._root_widget.children = [] current_row = Row() cond_idx = 0 for cond in self._conditions: cp = ColorPicker(color=self.colors.get(cond, "blue"), title=cond, width=60) cp.on_change( "color", lambda attr, old, new: self._update_color( cond, attr, old, new)) self.color_pickers[cond] = cp if cond_idx == self._columns: self._root_widget.children.append(current_row) current_row = Row() current_row.children.append(cp) self._root_widget.children.append(current_row)
def make_plot(data, title): clusterplot = make_cluster_plot(data) phaseplot = make_phase_plot(data) add_phaseplot_callback(clusterplot, phaseplot) title_div = Div(text=title) return Column( title_div, Row(clusterplot, phaseplot) )
def test_len(self) -> None: d = Document() dm = d.models assert len(dm) == 0 r1 = Row(children=[Div()]) r2 = Row(children=[Div(), Div()]) d.add_root(r1) assert len(dm) == 2 d.add_root(r2) assert len(dm) == 5 d.remove_root(r1) assert len(dm) == 3 d.remove_root(r2) assert len(dm) == 0
def _make_axes(self, plot): width, height = self.renderer.get_size(plot) x_axis, y_axis = None, None kwargs = dict(sizing_mode=self.sizing_mode) keys = self.layout.keys(full_grid=True) if self.xaxis: flip = self.shared_xaxis rotation = self.xrotation lsize = self._fontsize('xlabel').get('fontsize') tsize = self._fontsize('xticks', common=False).get('fontsize') xfactors = list(unique_iterator([wrap_tuple(k)[0] for k in keys])) x_axis = make_axis('x', width, xfactors, self.layout.kdims[0], flip=flip, rotation=rotation, label_size=lsize, tick_size=tsize) if self.yaxis and self.layout.ndims > 1: flip = self.shared_yaxis rotation = self.yrotation lsize = self._fontsize('ylabel').get('fontsize') tsize = self._fontsize('yticks', common=False).get('fontsize') yfactors = list(unique_iterator([k[1] for k in keys])) y_axis = make_axis('y', height, yfactors, self.layout.kdims[1], flip=flip, rotation=rotation, label_size=lsize, tick_size=tsize) if x_axis and y_axis: plot = filter_toolboxes(plot) r1, r2 = ([y_axis, plot], [None, x_axis]) if self.shared_xaxis: r1, r2 = r2, r1 if self.shared_yaxis: r1, r2 = r1[::-1], r2[::-1] models = layout_padding([r1, r2], self.renderer) plot = gridplot(models, **kwargs) elif y_axis: models = [y_axis, plot] if self.shared_yaxis: models = models[::-1] plot = Row(*models, **kwargs) elif x_axis: models = [plot, x_axis] if self.shared_xaxis: models = models[::-1] plot = Column(*models, **kwargs) return plot
def plot_church_data(): args = parse_args() load_saved_visible_categories() conn = sql.connect(app.config['DB_LOCATION']) church_info = pd.read_sql("select * from churches", conn) if not validate_filters(church_info, args['filter_by'][0], args['filter_choice'][0]): raise LegacyException("Invalid filter parameters %s %s" % (args['filter_by'][0], args['filter_choice'][0])) filter_widget, selected = make_filter_widget(church_info, args['filter_by'][0], args['filter_choice'][0]) for prop in args['properties']: if not is_valid_category(prop): raise LegacyException("Invalid property %s" % prop) set_category_visibility(prop) if args['plot_type'][0] not in PLOT_TYPES: raise LegacyException("Invalid plot type %s" % args['plot_type'][0]) if args['plot_type'][0] == "Time Series": church_data = load_churches_data(conn, args['properties'][:1], args['filter_by'][0], selected) plot = make_time_series_plot(church_data, args['properties'][0]) elif args['plot_type'][0] == "Histogram": church_data = load_churches_data(conn, args['properties'][:1], args['filter_by'][0], selected) plot = make_histogram_plot(church_data, args['properties'][0]) elif args['plot_type'][0] == "Comparison": church_data = load_churches_data(conn, args['properties'], args['filter_by'][0], selected) plot = make_comparison_plot(church_data, args['properties']) plot_app = Column( make_plot_type_buttons(args['plot_type'][0]), Row(plot, filter_widget), ) script, div = components(plot_app) html = flask.render_template('index.html', plot_script=script, plot_div=div, **args) return html
def champion_count_tier(self, champion_count_tier_df): """ Build units_count_tier_plot for winner and loser group tabs: 6 tabs, cost of champion x_axis: champion name y_axis: champion usage count in stack of tier scatter: average tier of champion """ output_file( f"assets/plot/{self.file_name_prefix}/units_count_tier_plot.html") champion_count_tier_df = champion_count_tier_df.sort_values( by=['count']) # Plot with all units panels = [] fig, background_image = champion_count_tier.build_plot( champion_count_tier_df, theme=unit_stacked_bar_theme) panels += [ Panel(child=Row(fig, background_image), title='All Champions') ] # Plot by cost of units units_df_by_cost = split_df_by_champion_cost(set_name='set3', df=champion_count_tier_df) for index, df_data in enumerate(units_df_by_cost.values()): cost_unit_df = pd.DataFrame(df_data, columns=champion_count_tier_df.columns) fig, background_image = champion_count_tier.build_plot( cost_unit_df, theme=unit_stacked_bar_theme) panels += [ Panel(child=Row(fig, background_image), title=f'{index+1} Cost Champions') ] tabs = Tabs(tabs=panels) save(tabs)
def test_recompute(self) -> None: d = Document() dm = d.models assert len(dm) == 0 r1 = Row(children=[Div(id="d1", name="dr1")]) r2 = Row(children=[Div(id="d2", name="dr2"), Div(id="d3", name="dr2")]) d.add_root(r1) d.add_root(r2) assert set(dm._models_by_name._dict) == {"dr1", "dr2"} for m in dm: assert m._document is d d.remove_root(r1) for m in dm: assert m._document is d assert r1._document is None assert r1.children[0]._document is None assert set(dm._models_by_name._dict) == {"dr2"}
def plotnoise(noisepkl, mergepkl, plot_width=950, plot_height=400): """ Make two panel plot to summary noise analysis with estimated flux scale """ d = pickle.load(open(mergepkl)) ndist, imstd, flagfrac = plotnoisedist(noisepkl, plot_width=plot_width / 2, plot_height=plot_height) fluxscale = calcfluxscale(d, imstd, flagfrac) logger.info('Median image noise is {0:.3} Jy.'.format(fluxscale * imstd)) ncum, imnoise = plotnoisecum(noisepkl, fluxscale=fluxscale, plot_width=plot_width / 2, plot_height=plot_height) hndle = show(Row(ndist, ncum, width=plot_width, height=plot_height)) return imnoise
def make_document(self, doc): doc.title = "Connor's MACD autotrader" doc.add_periodic_callback(self.update, 5000) #https://stackoverflow.com/questions/56137866/how-to-display-plot-in-bokeh-div #stuff on the side of graph external = Column() external.children.append(self.priceDIV) external.children.append(self.positionDIV) external.children.append(self.lastTradeDIV) layout = Row() layout.children.append(self.plot) layout.children.append(external) doc.add_root(layout)
def make_category_select(selected_props): selected_props = selected_props if isinstance(selected_props, list) else [selected_props] children = [] for cb_index, prop in enumerate(selected_props): cb_values = ['"{prop}"'.format(prop=prop) for prop in selected_props] cb_values[cb_index] = 'cb_obj.value' cb_string = '[' + ','.join(cb_values) + ']' children.append( Select( title="Choose a category...", options=list(get_visible_category_strings()), callback=CustomJS(code="reloadWithParams('properties', %s)" % cb_string), value=prop, )) return Row(children=children)
def __initialize_bokeh_graphics(self): """ Bokeh grafikonok alap elrendezese. """ self.line1_color = "#FF4242" self.line2_color = "#0A284B" self.line3_color = "#0072B2" self.select_widget = Select(title="Valutapár", options=list(self.__asset_pairs.keys()), value="XBTUSD") self.select_widget.on_change("value", self.__change_asset_pair) self.__asset_pair = self.__asset_pairs[self.select_widget.value] self.title_div = Div(text="<b>Kriptovaluta árfolyamok</b>", style={ "font-size": "150%", "height": "50px" }) self.price_div = Div(text="<b> </b>", style={ "font-size": "200%", "color": self.line1_color }) self.avg10_div = Div(text="<b> </b>", style={ "font-size": "150%", "color": self.line2_color }) self.avg40_div = Div(text="<b> </b>", style={ "font-size": "150%", "color": self.line3_color }) self.controls = Column(self.title_div, self.select_widget, self.price_div, self.avg10_div, self.avg40_div) self.__make_plot() self.layout = Row(self.controls, Column(self.plot1, self.plot2)) curdoc().theme = "light_minimal"
def test_repeated_children() -> None: def test(layout: LayoutDOM) -> None: with mock.patch("bokeh.core.validation.check.log") as mock_logger: check_integrity([layout]) assert mock_logger.error.call_count == 1 assert mock_logger.error.call_args[0][0].startswith( "E-1027 (REPEATED_LAYOUT_CHILD): The same model can't be used multiple times in a layout" ) p0 = figure() p1 = figure() test(Row(children=[p0, p1, p0])) test(row(p0, p1, p0)) test(Column(children=[p0, p1, p0])) test(column(p0, p1, p0)) test(GridBox(children=[(p0, 0, 0), (p1, 1, 0), (p0, 2, 0)])) test(gridplot([[p0], [p1], [p0]], toolbar_location=None))
def linked_panning(): N = 100 x = np.linspace(0, 4 * np.pi, N) y1 = np.sin(x) y2 = np.cos(x) y3 = np.sin(x) + np.cos(x) s1 = figure(tools=tools, toolbar_location='right', responsive='box') s1.circle(x, y1, color="navy", size=8, alpha=0.5) s2 = figure(tools=tools, toolbar_location='right', x_range=s1.x_range, y_range=s1.y_range, responsive='box') s2.circle(x, y2, color="firebrick", size=8, alpha=0.5) s3 = figure(tools='pan, box_select', toolbar_location='right', x_range=s1.x_range, responsive='box') s3.circle(x, y3, color="olive", size=8, alpha=0.5) layout = Row(s1, s2, s3, responsive='box') return layout
def __init__(self): self.plot = bokeh.plotting.figure( plot_width=500, plot_height=500, x_range=Range1d(0, 1, bounds=(-0.25, 1.25)), y_range=Range1d(0, 1, bounds=(-0.25, 1.25)), ) self.plot.tools.pop(-1) # remove help tool self.plot.tools.pop(-2) # remove save tool self.plot.toolbar.active_scroll = self.plot.tools[ 1] # activate wheel scroll self.plot.toolbar.logo = None self.plot.xaxis.visible = False self.plot.yaxis.visible = False self.plot.xgrid.grid_line_color = None self.plot.ygrid.grid_line_color = None self.plot.outline_line_alpha = 0 menu = [] self.imgSelectDropDown: Dropdown = Dropdown(label="SelectImage", button_type="warning", menu=menu) self.widget = Panel(child=Row(self.plot, self.imgSelectDropDown), title='Images')
def create_layout(self): # create figure self.x_range = Range1d(start=self.model.map_extent[0], end=self.model.map_extent[2], bounds=None) self.y_range = Range1d(start=self.model.map_extent[1], end=self.model.map_extent[3], bounds=None) self.fig = Figure(tools='wheel_zoom,pan', x_range=self.x_range, lod_threshold=None, plot_width=self.model.plot_width, plot_height=self.model.plot_height, background_fill_color='black', y_range=self.y_range) self.fig.min_border_top = 0 self.fig.min_border_bottom = 10 self.fig.min_border_left = 0 self.fig.min_border_right = 0 self.fig.axis.visible = False self.fig.xgrid.grid_line_color = None self.fig.ygrid.grid_line_color = None # add tiled basemap self.tile_source = WMTSTileSource(url=self.model.basemap) self.tile_renderer = TileRenderer(tile_source=self.tile_source) self.fig.renderers.append(self.tile_renderer) # add datashader layer self.image_source = ImageSource( url=self.model.service_url, extra_url_vars=self.model.shader_url_vars) self.image_renderer = DynamicImageRenderer( image_source=self.image_source) self.fig.renderers.append(self.image_renderer) # add label layer self.label_source = WMTSTileSource(url=self.model.labels_url) self.label_renderer = TileRenderer(tile_source=self.label_source) self.fig.renderers.append(self.label_renderer) # Add placeholder for legends (temporarily disabled) # self.model.legend_side_vbox = Column() # self.model.legend_bottom_vbox = Column() # add ui components controls = [] axes_select = Select(name='Axes', options=list(self.model.axes.keys())) axes_select.on_change('value', self.on_axes_change) controls.append(axes_select) self.field_select = Select(name='Field', options=list(self.model.fields.keys())) self.field_select.on_change('value', self.on_field_change) controls.append(self.field_select) self.aggregate_select = Select( name='Aggregate', options=list(self.model.aggregate_functions.keys())) self.aggregate_select.on_change('value', self.on_aggregate_change) controls.append(self.aggregate_select) transfer_select = Select(name='Transfer Function', options=list( self.model.transfer_functions.keys())) transfer_select.on_change('value', self.on_transfer_function_change) controls.append(transfer_select) color_ramp_select = Select(name='Color Ramp', options=list(self.model.color_ramps.keys())) color_ramp_select.on_change('value', self.on_color_ramp_change) controls.append(color_ramp_select) spread_size_slider = Slider(title="Spread Size (px)", value=0, start=0, end=10, step=1) spread_size_slider.on_change('value', self.on_spread_size_change) controls.append(spread_size_slider) # hover (temporarily disabled) #hover_size_slider = Slider(title="Hover Size (px)", value=8, start=4, # end=30, step=1) #hover_size_slider.on_change('value', self.on_hover_size_change) #controls.append(hover_size_slider) # legends (temporarily disabled) # controls.append(self.model.legend_side_vbox) # add map components basemap_select = Select(name='Basemap', value='Imagery', options=list(self.model.basemaps.keys())) basemap_select.on_change('value', self.on_basemap_change) image_opacity_slider = Slider(title="Opacity", value=100, start=0, end=100, step=1) image_opacity_slider.on_change('value', self.on_image_opacity_slider_change) basemap_opacity_slider = Slider(title="Basemap Opacity", value=100, start=0, end=100, step=1) basemap_opacity_slider.on_change('value', self.on_basemap_opacity_slider_change) show_labels_chk = CheckboxGroup(labels=["Show Labels"], active=[0]) show_labels_chk.on_click(self.on_labels_change) map_controls = [ basemap_select, basemap_opacity_slider, image_opacity_slider, show_labels_chk ] self.controls = Column(height=600, children=controls) self.map_controls = Row(width=self.fig.plot_width, children=map_controls) # legends (temporarily disabled) self.map_area = Column(width=900, height=600, children=[self.map_controls, self.fig]) self.layout = Row(width=1300, height=600, children=[self.controls, self.map_area]) self.model.fig = self.fig self.model.update_hover()
def draw(S, position=None, with_labels=False): """Plot the given signed social network. Args: S: The network position (dict, optional): The position for the nodes. If no position is provided, a layout will be calculated. If the nodes have 'color' attributes, a Kamanda-Kawai layout will be used to group nodes of the same color together. Otherwise, a circular layout will be used. Returns: A dictionary of positions keyed by node. Examples: >>> import dwave_structural_imbalance_demo as sbdemo >>> gssn = sbdemo.GlobalSignedSocialNetwork() >>> nld_before = gssn.get_node_link_data('Syria', 2013) >>> nld_after = gssn.solve_structural_imbalance('Syria', 2013) # draw Global graph before solving; save node layout for reuse >>> position = sbdemo.draw('syria.png', nld_before) # draw the Global graph; reusing the above layout, and calculating a new grouped layout >>> sbdemo.draw('syria_imbalance.png', nld_after, position) >>> sbdemo.draw('syria_imbalance_grouped', nld_after) """ # we need a consistent ordering of the edges edgelist = S.edges() nodelist = S.nodes() def layout_wrapper(S): pos = position if pos is None: try: # group bipartition if nodes are colored dist = defaultdict(dict) for u, v in product(nodelist, repeat=2): if u == v: # node has no distance from itself dist[u][v] = 0 elif nodelist[u]['color'] == nodelist[v]['color']: # make same color nodes closer together dist[u][v] = 1 else: # make different color nodes further apart dist[u][v] = 2 pos = nx.kamada_kawai_layout(S, dist) except KeyError: # default to circular layout if nodes aren't colored pos = nx.circular_layout(S) return pos # call layout wrapper once with all nodes to store position for calls with partial graph position = layout_wrapper(S) plot = Plot(plot_width=600, plot_height=400, x_range=Range1d(-1.2, 1.2), y_range=Range1d(-1.2, 1.2)) tools = [WheelZoomTool(), ZoomInTool(), ZoomOutTool(), PanTool()] plot.add_tools(*tools) plot.toolbar.active_scroll = tools[0] def get_graph_renderer(S, line_dash): # we need a consistent ordering of the edges edgelist = S.edges() nodelist = S.nodes() # get the colors assigned to each edge based on friendly/hostile sign_edge_color = ['#87DACD' if S[u][v]['sign'] == 1 else '#FC9291' for u, v in edgelist] # get the colors assigned to each node by coloring try: coloring_node_color = ['#4378F8' if nodelist[v]['color'] else '#FFE897' for v in nodelist] except KeyError: coloring_node_color = ['#FFFFFF' for __ in nodelist] graph_renderer = from_networkx(S, layout_wrapper) circle_size = 10 graph_renderer.node_renderer.data_source.add(coloring_node_color, 'color') graph_renderer.node_renderer.glyph = Circle(size=circle_size, fill_color='color') edge_size = 2 graph_renderer.edge_renderer.data_source.add(sign_edge_color, 'color') try: graph_renderer.edge_renderer.data_source.add([S[u][v]['event_year'] for u, v in edgelist], 'event_year') graph_renderer.edge_renderer.data_source.add( [S[u][v]['event_description'] for u, v in edgelist], 'event_description') plot.add_tools(HoverTool(tooltips=[("Year", "@event_year"), ("Description", "@event_description")], line_policy="interp")) except KeyError: pass graph_renderer.edge_renderer.glyph = MultiLine(line_color='color', line_dash=line_dash) graph_renderer.inspection_policy = EdgesAndLinkedNodes() return graph_renderer try: S_dash = S.edge_subgraph(((u, v) for u, v in edgelist if S[u][v]['frustrated'])) S_solid = S.edge_subgraph(((u, v) for u, v in edgelist if not S[u][v]['frustrated'])) plot.renderers.append(get_graph_renderer(S_dash, 'dashed')) plot.renderers.append(get_graph_renderer(S_solid, 'solid')) except KeyError: plot.renderers.append(get_graph_renderer(S, 'solid')) plot.background_fill_color = "#202239" positions = layout_wrapper(S) if with_labels: data = { 'xpos': [], 'ypos': [], 'label': [] } for label, pos in positions.items(): data['label'].append(label) data['xpos'].append(pos[0]) data['ypos'].append(pos[1]) labels = LabelSet(x='xpos', y='ypos', text='label', level='glyph', source=ColumnDataSource(data), x_offset=-5, y_offset=10, text_color="#F5F7FB", text_font_size='12pt') plot.add_layout(labels) show(Row(plot)) return positions
def initialize_plot(self, plots=None, ranges=None): ranges = self.compute_ranges(self.layout, self.keys[-1], None) passed_plots = [] if plots is None else plots plots = [[] for _ in range(self.rows)] tab_titles = {} insert_rows, insert_cols = [], [] adjoined = False for r, c in self.coords: subplot = self.subplots.get((r, c), None) if subplot is not None: shared_plots = passed_plots if self.shared_axes else None subplots = subplot.initialize_plot(ranges=ranges, plots=shared_plots) # Computes plotting offsets depending on # number of adjoined plots offset = sum(r >= ir for ir in insert_rows) if len(subplots) > 2: adjoined = True # Add pad column in this position insert_cols.append(c) if r not in insert_rows: # Insert and pad marginal row if none exists plots.insert(r+offset, [None for _ in range(len(plots[r]))]) # Pad previous rows for ir in range(r): plots[ir].insert(c+1, None) # Add to row offset insert_rows.append(r) offset += 1 # Add top marginal plots[r+offset-1] += [subplots.pop(-1), None] elif len(subplots) > 1: adjoined = True # Add pad column in this position insert_cols.append(c) # Pad previous rows for ir in range(r): plots[r].insert(c+1, None) # Pad top marginal if one exists if r in insert_rows: plots[r+offset-1] += 2*[None] else: # Pad top marginal if one exists if r in insert_rows: plots[r+offset-1] += [None] * (1+(c in insert_cols)) plots[r+offset] += subplots if len(subplots) == 1 and c in insert_cols: plots[r+offset].append(None) passed_plots.append(subplots[0]) if self.tabs: title = subplot.subplots['main']._format_title(self.keys[-1], dimensions=False) if not title: title = ' '.join(self.paths[r,c]) tab_titles[r, c] = title else: plots[r+offset] += [empty_plot(0, 0)] # Replace None types with empty plots # to avoid bokeh bug plots = layout_padding(plots, self.renderer) # Wrap in appropriate layout model if self.tabs: panels = [Panel(child=child, title=str(tab_titles.get((r, c)))) for r, row in enumerate(plots) for c, child in enumerate(row) if child is not None] layout_plot = Tabs(tabs=panels) elif bokeh_version >= '0.12': plots = filter_toolboxes(plots) plots, width = pad_plots(plots) layout_plot = gridplot(children=plots, width=width) elif len(plots) == 1 and not adjoined: layout_plot = Column(children=[Row(children=plots[0])]) elif len(plots[0]) == 1: layout_plot = Column(children=[p[0] for p in plots]) else: layout_plot = BokehGridPlot(children=plots) title = self._get_title(self.keys[-1]) if title: self.handles['title'] = title layout_plot = Column(title, layout_plot) self._update_callbacks(layout_plot) self.handles['plot'] = layout_plot self.handles['plots'] = plots if self.shared_datasource: self.sync_sources() self.drawn = True return self.handles['plot']
plot_1.title.text = "Circular Layout (NodesAndLinkedEdges inspection policy)" plot_1.add_tools(HoverTool(tooltips=None)) plot_2 = create_graph(nx.spring_layout, selection_policy=NodesAndLinkedEdges(), scale=2, center=(0, 0)) plot_2.title.text = "Spring Layout (NodesAndLinkedEdges selection policy)" plot_2.add_tools(TapTool(), BoxSelectTool()) plot_3 = create_graph(nx.random_layout, inspection_policy=EdgesAndLinkedNodes(), center=(0, 0)) plot_3.title.text = "Random Layout (EdgesAndLinkedNodes inspection policy)" plot_3.add_tools(HoverTool(tooltips=None)) plot_4 = create_graph(nx.fruchterman_reingold_layout, selection_policy=EdgesAndLinkedNodes(), scale=2, center=(0, 0), dim=2) plot_4.title.text = "FR Layout (EdgesAndLinkedNodes selection policy)" plot_4.add_tools(TapTool()) layout = Column(Row(plot_1, plot_2), Row(plot_3, plot_4)) doc = curdoc() doc.add_root(layout) show(layout)
def plot_cross_section_bokeh(filename, map_data_all_slices, map_depth_all_slices, \ color_range_all_slices, cross_data, boundary_data, \ style_parameter): ''' Plot shear velocity maps and cross-sections using bokeh Input: filename is the filename of the resulting html file map_data_all_slices contains the velocity model parameters saved for map view plots map_depth_all_slices is a list of depths color_range_all_slices is a list of color ranges profile_data_all is a list of velocity profiles cross_lat_data_all is a list of cross-sections along latitude lat_value_all is a list of corresponding latitudes for these cross-sections cross_lon_data_all is a list of cross-sections along longitude lon_value_all is a list of corresponding longitudes for these cross-sections boundary_data is a list of boundaries style_parameter contains parameters to customize the plots Output: None ''' xlabel_fontsize = style_parameter['xlabel_fontsize'] # colorbar_data_all_left = [] colorbar_data_all_right = [] map_view_ndepth = style_parameter['map_view_ndepth'] palette_r = palette[::-1] ncolor = len(palette_r) colorbar_top = [0.1 for i in range(ncolor)] colorbar_bottom = [0 for i in range(ncolor)] map_data_all_slices_depth = [] for idepth in range(map_view_ndepth): color_min = color_range_all_slices[idepth][0] color_max = color_range_all_slices[idepth][1] color_step = (color_max - color_min)*1./ncolor colorbar_left = np.linspace(color_min,color_max-color_step,ncolor) colorbar_right = np.linspace(color_min+color_step,color_max,ncolor) colorbar_data_all_left.append(colorbar_left) colorbar_data_all_right.append(colorbar_right) map_depth = map_depth_all_slices[idepth] map_data_all_slices_depth.append('Depth: {0:8.0f} km'.format(map_depth)) # data for the colorbar colorbar_data_one_slice = {} colorbar_data_one_slice['colorbar_left'] = colorbar_data_all_left[style_parameter['map_view_default_index']] colorbar_data_one_slice['colorbar_right'] = colorbar_data_all_right[style_parameter['map_view_default_index']] colorbar_data_one_slice_bokeh = ColumnDataSource(data=dict(colorbar_top=colorbar_top,colorbar_bottom=colorbar_bottom,\ colorbar_left=colorbar_data_one_slice['colorbar_left'],\ colorbar_right=colorbar_data_one_slice['colorbar_right'],\ palette_r=palette_r)) colorbar_data_all_slices_bokeh = ColumnDataSource(data=dict(colorbar_data_all_left=colorbar_data_all_left,\ colorbar_data_all_right=colorbar_data_all_right)) # map_view_label_lon = style_parameter['map_view_depth_label_lon'] map_view_label_lat = style_parameter['map_view_depth_label_lat'] map_data_one_slice_depth = map_data_all_slices_depth[style_parameter['map_view_default_index']] map_data_one_slice_depth_bokeh = ColumnDataSource(data=dict(lat=[map_view_label_lat], lon=[map_view_label_lon], map_depth=[map_data_one_slice_depth])) # map_view_default_index = style_parameter['map_view_default_index'] #map_data_one_slice = map_data_all_slices[map_view_default_index] map_color_all_slices = [] for i in range(len(map_data_all_slices)): vmin, vmax = color_range_all_slices[i] map_color = val_to_rgb(map_data_all_slices[i], palette_r, vmin, vmax) map_color_all_slices.append(map_color) map_color_one_slice = map_color_all_slices[map_view_default_index] # map_data_one_slice_bokeh = ColumnDataSource(data=dict(x=[style_parameter['map_view_image_lon_min']],\ y=[style_parameter['map_view_image_lat_min']],dw=[style_parameter['nlon']],\ dh=[style_parameter['nlat']],map_data_one_slice=[map_color_one_slice])) map_data_all_slices_bokeh = ColumnDataSource(data=dict(map_data_all_slices=map_color_all_slices,\ map_data_all_slices_depth=map_data_all_slices_depth)) # plot_depth = np.shape(cross_data)[0] * style_parameter['cross_ddepth'] plot_lon = great_arc_distance(style_parameter['cross_default_lat0'], style_parameter['cross_default_lon0'],\ style_parameter['cross_default_lat1'], style_parameter['cross_default_lon1']) vs_min = style_parameter['cross_view_vs_min'] vs_max = style_parameter['cross_view_vs_max'] cross_color = val_to_rgb(cross_data, palette_r, vmin, vmax) cross_data_bokeh = ColumnDataSource(data=dict(x=[0],\ y=[plot_depth],dw=[plot_lon],\ dh=[plot_depth],cross_data=[cross_color])) map_line_bokeh = ColumnDataSource(data=dict(lat=[style_parameter['cross_default_lat0'], style_parameter['cross_default_lat1']],\ lon=[style_parameter['cross_default_lon0'], style_parameter['cross_default_lon1']])) # ncolor_cross = len(my_palette) colorbar_top_cross = [0.1 for i in range(ncolor_cross)] colorbar_bottom_cross = [0 for i in range(ncolor_cross)] color_min_cross = style_parameter['cross_view_vs_min'] color_max_cross = style_parameter['cross_view_vs_max'] color_step_cross = (color_max_cross - color_min_cross)*1./ncolor_cross colorbar_left_cross = np.linspace(color_min_cross, color_max_cross-color_step_cross, ncolor_cross) colorbar_right_cross = np.linspace(color_min_cross+color_step_cross, color_max_cross, ncolor_cross) # ============================== map_view = Figure(plot_width=style_parameter['map_view_plot_width'], plot_height=style_parameter['map_view_plot_height'], \ tools=style_parameter['map_view_tools'], title=style_parameter['map_view_title'], \ y_range=[style_parameter['map_view_figure_lat_min'], style_parameter['map_view_figure_lat_max']],\ x_range=[style_parameter['map_view_figure_lon_min'], style_parameter['map_view_figure_lon_max']]) # map_view.image_rgba('map_data_one_slice',x='x',\ y='y',dw='dw',dh='dh',\ source=map_data_one_slice_bokeh, level='image') depth_slider_callback = CustomJS(args=dict(map_data_one_slice_bokeh=map_data_one_slice_bokeh,\ map_data_all_slices_bokeh=map_data_all_slices_bokeh,\ colorbar_data_all_slices_bokeh=colorbar_data_all_slices_bokeh,\ colorbar_data_one_slice_bokeh=colorbar_data_one_slice_bokeh,\ map_data_one_slice_depth_bokeh=map_data_one_slice_depth_bokeh), code=""" var d_index = Math.round(cb_obj.value) var map_data_all_slices = map_data_all_slices_bokeh.data map_data_one_slice_bokeh.data['map_data_one_slice'] = [map_data_all_slices['map_data_all_slices'][d_index]] map_data_one_slice_bokeh.change.emit() var color_data_all_slices = colorbar_data_all_slices_bokeh.data colorbar_data_one_slice_bokeh.data['colorbar_left'] = color_data_all_slices['colorbar_data_all_left'][d_index] colorbar_data_one_slice_bokeh.data['colorbar_right'] = color_data_all_slices['colorbar_data_all_right'][d_index] colorbar_data_one_slice_bokeh.change.emit() map_data_one_slice_depth_bokeh.data['map_depth'] = [map_data_all_slices['map_data_all_slices_depth'][d_index]] map_data_one_slice_depth_bokeh.change.emit() """) depth_slider = Slider(start=0, end=style_parameter['map_view_ndepth']-1, \ value=map_view_default_index, step=1, \ width=style_parameter['map_view_plot_width'],\ title=style_parameter['depth_slider_title'], height=50, \ callback=depth_slider_callback) # ------------------------------ # add boundaries to map view # country boundaries map_view.multi_line(boundary_data['country']['longitude'],\ boundary_data['country']['latitude'],color='black',\ line_width=2, level='underlay',nonselection_line_alpha=1.0,\ nonselection_line_color='black') # marine boundaries map_view.multi_line(boundary_data['marine']['longitude'],\ boundary_data['marine']['latitude'],color='black',\ level='underlay',nonselection_line_alpha=1.0,\ nonselection_line_color='black') # shoreline boundaries map_view.multi_line(boundary_data['shoreline']['longitude'],\ boundary_data['shoreline']['latitude'],color='black',\ line_width=2, level='underlay',nonselection_line_alpha=1.0,\ nonselection_line_color='black') # state boundaries map_view.multi_line(boundary_data['state']['longitude'],\ boundary_data['state']['latitude'],color='black',\ level='underlay',nonselection_line_alpha=1.0,\ nonselection_line_color='black') # ------------------------------ # add depth label map_view.rect(style_parameter['map_view_depth_box_lon'], style_parameter['map_view_depth_box_lat'], \ width=style_parameter['map_view_depth_box_width'], height=style_parameter['map_view_depth_box_height'], \ width_units='screen',height_units='screen', color='#FFFFFF', line_width=1., line_color='black', level='underlay') map_view.text('lon', 'lat', 'map_depth', source=map_data_one_slice_depth_bokeh,\ text_font_size=style_parameter['annotating_text_font_size'],text_align='left',level='underlay') # ------------------------------ map_view.line('lon', 'lat', source=map_line_bokeh, line_dash=[8,2,8,2], line_color='#00ff00',\ nonselection_line_alpha=1.0, line_width=5.,\ nonselection_line_color='black') map_view.text([style_parameter['cross_default_lon0']],[style_parameter['cross_default_lat0']], ['A'], \ text_font_size=style_parameter['title_font_size'],text_align='left') map_view.text([style_parameter['cross_default_lon1']],[style_parameter['cross_default_lat1']], ['B'], \ text_font_size=style_parameter['title_font_size'],text_align='left') # ------------------------------ # change style map_view.title.text_font_size = style_parameter['title_font_size'] map_view.title.align = 'center' map_view.title.text_font_style = 'normal' map_view.xaxis.axis_label = style_parameter['map_view_xlabel'] map_view.xaxis.axis_label_text_font_style = 'normal' map_view.xaxis.axis_label_text_font_size = xlabel_fontsize map_view.xaxis.major_label_text_font_size = xlabel_fontsize map_view.yaxis.axis_label = style_parameter['map_view_ylabel'] map_view.yaxis.axis_label_text_font_style = 'normal' map_view.yaxis.axis_label_text_font_size = xlabel_fontsize map_view.yaxis.major_label_text_font_size = xlabel_fontsize map_view.xgrid.grid_line_color = None map_view.ygrid.grid_line_color = None map_view.toolbar.logo = None map_view.toolbar_location = 'above' map_view.toolbar_sticky = False # ============================== # plot colorbar colorbar_fig = Figure(tools=[], y_range=(0,0.1),plot_width=style_parameter['map_view_plot_width'], \ plot_height=style_parameter['colorbar_plot_height'],title=style_parameter['colorbar_title']) colorbar_fig.toolbar_location=None colorbar_fig.quad(top='colorbar_top',bottom='colorbar_bottom',left='colorbar_left',right='colorbar_right',\ color='palette_r',source=colorbar_data_one_slice_bokeh) colorbar_fig.yaxis[0].ticker=FixedTicker(ticks=[]) colorbar_fig.xgrid.grid_line_color = None colorbar_fig.ygrid.grid_line_color = None colorbar_fig.xaxis.axis_label_text_font_size = xlabel_fontsize colorbar_fig.xaxis.major_label_text_font_size = xlabel_fontsize colorbar_fig.xaxis[0].formatter = PrintfTickFormatter(format="%5.2f") colorbar_fig.title.text_font_size = xlabel_fontsize colorbar_fig.title.align = 'center' colorbar_fig.title.text_font_style = 'normal' # ============================== # annotating text annotating_fig01 = Div(text=style_parameter['annotating_html01'], \ width=style_parameter['annotation_plot_width'], height=style_parameter['annotation_plot_height']) annotating_fig02 = Div(text="""<p style="font-size:16px">""", \ width=style_parameter['annotation_plot_width'], height=style_parameter['annotation_plot_height']) # ============================== # plot cross-section along latitude cross_section_plot_width = int(style_parameter['cross_plot_height']*1.0/plot_depth*plot_lon/10.) cross_view = Figure(plot_width=cross_section_plot_width, plot_height=style_parameter['cross_plot_height'], \ tools=style_parameter['cross_view_tools'], title=style_parameter['cross_view_title'], \ y_range=[plot_depth, -30],\ x_range=[0, plot_lon]) cross_view.image_rgba('cross_data',x='x',\ y='y',dw='dw',dh='dh',\ source=cross_data_bokeh, level='image') cross_view.text([plot_lon*0.1], [-10], ['A'], \ text_font_size=style_parameter['title_font_size'],text_align='left',level='underlay') cross_view.text([plot_lon*0.9], [-10], ['B'], \ text_font_size=style_parameter['title_font_size'],text_align='left',level='underlay') # ------------------------------ # change style cross_view.title.text_font_size = style_parameter['title_font_size'] cross_view.title.align = 'center' cross_view.title.text_font_style = 'normal' cross_view.xaxis.axis_label = style_parameter['cross_view_xlabel'] cross_view.xaxis.axis_label_text_font_style = 'normal' cross_view.xaxis.axis_label_text_font_size = xlabel_fontsize cross_view.xaxis.major_label_text_font_size = xlabel_fontsize cross_view.yaxis.axis_label = style_parameter['cross_view_ylabel'] cross_view.yaxis.axis_label_text_font_style = 'normal' cross_view.yaxis.axis_label_text_font_size = xlabel_fontsize cross_view.yaxis.major_label_text_font_size = xlabel_fontsize cross_view.xgrid.grid_line_color = None cross_view.ygrid.grid_line_color = None cross_view.toolbar.logo = None cross_view.toolbar_location = 'right' cross_view.toolbar_sticky = False # ============================== colorbar_fig_right = Figure(tools=[], y_range=(0,0.1),plot_width=cross_section_plot_width, \ plot_height=style_parameter['colorbar_plot_height'],title=style_parameter['colorbar_title']) colorbar_fig_right.toolbar_location=None colorbar_fig_right.quad(top=colorbar_top_cross,bottom=colorbar_bottom_cross,\ left=colorbar_left_cross,right=colorbar_right_cross,\ color=my_palette) colorbar_fig_right.yaxis[0].ticker=FixedTicker(ticks=[]) colorbar_fig_right.xgrid.grid_line_color = None colorbar_fig_right.ygrid.grid_line_color = None colorbar_fig_right.xaxis.axis_label_text_font_size = xlabel_fontsize colorbar_fig_right.xaxis.major_label_text_font_size = xlabel_fontsize colorbar_fig_right.xaxis[0].formatter = PrintfTickFormatter(format="%5.2f") colorbar_fig_right.title.text_font_size = xlabel_fontsize colorbar_fig_right.title.align = 'center' colorbar_fig_right.title.text_font_style = 'normal' # ============================== output_file(filename,title=style_parameter['html_title'], mode=style_parameter['library_source']) left_column = Column(depth_slider, map_view, colorbar_fig, annotating_fig01, width=style_parameter['left_column_width']) right_column = Column(annotating_fig02, cross_view, colorbar_fig_right, width=cross_section_plot_width) layout = Row(left_column, right_column, height=800) save(layout)
all_tools = plot_3.toolbar.tools + plot_2.toolbar.tools toolbar = Toolbar(tools=all_tools) #doc.add_root( # gridplot([[plot_3]], sizing_mode='height_ar', toolbar_location='above') #) #doc.add_root( # Column( # Row(plot_2, plot_3, sizing_mode='width_ar'), # Row(plot_4, plot_5, sizing_mode='width_ar'), # sizing_mode='width_ar' # ) #) # doc.add_root(Row(plot_3, sizing_mode='scale_width')) #doc.add_root(plot_3) #doc.add_root(slider_1) #col1 = Column( # Row(plot_1, sizing_mode='box'), # Row(plot_2, plot_3, plot_4, sizing_mode='box'), # Row(plot_5, plot_6, sizing_mode='box'), # sizing_mode='box' #) #doc.add_root(col1) #col2 = Column(plot_3, plot_4) #doc.add_root(Row(col1, col2)) #doc.add_root(Row(plot_1, plot_2)) #doc.add_root(Column(Row(button_1, button_2), Row(button_3, button_4))) # Row of two columns
def integration_with_sliders( rsys, tend, c0, parameters, fig_kwargs=None, slider_kwargs=None, conc_bounds=None, x_axis_type="linear", y_axis_type="linear", integrate_kwargs=None, odesys_extra=None, get_odesys_kw=None, integrate=None, ): """ Parameters ---------- rsys : ReactionSystem tend : float like c0 : dict Initial concentrations. parameters : dict Parameter values. fig_kwargs : dict Keyword-arguments passed to bokeh's ``Figure``. slider_kwargs : dict Keyword-arguments passed to bokeh's ``Slider``. conc_bounds : dict of dicts Mapping substance key to dict of bounds ('start', 'end', 'step'). x_axis_type : str y_axis_type : str integrate_kwargs : dict Keyword-arguments passed to integrate. odesys_extra : tuple If odesys & extra have already been generated (avoids call to ``get_odesys``). get_odesys_kw : dict Keyword-arguments passed to ``get_odesys``. integrate : callback Defaults to ``odesys.integrate``. """ import numpy as np from bokeh.plotting import Figure from bokeh.models import ColumnDataSource, Column, Row from bokeh.models.widgets import Slider if slider_kwargs is None: slider_kwargs = {} if get_odesys_kw is None: get_odesys_kw = {} if odesys_extra is None: odesys, extra = get_odesys(rsys, **get_odesys_kw) else: odesys, extra = odesys_extra if integrate is None: integrate = odesys.integrate state_keys, rarg_keys, p_units = [ extra[k] for k in ("param_keys", "unique", "p_units") ] output_conc_unit = get_odesys_kw.get("output_conc_unit", None) output_time_unit = get_odesys_kw.get("output_time_unit", None) unit_registry = get_odesys_kw.get("unit_registry", None) if output_conc_unit is None: if unit_registry is not None: raise ValueError( "if unit_registry is given, output_conc_unit must also be given" ) output_conc_unit = 1 if output_time_unit is None: if unit_registry is not None: raise ValueError( "if unit_registry is given, output_time_unit must also be given" ) output_conc_unit = 1 param_keys = list(chain(state_keys, rarg_keys)) if x_axis_type == "linear": tout = linspace(tend * 0, tend) elif x_axis_type == "log": tout = logspace_from_lin(tend * 1e-9, tend) else: raise NotImplementedError("Unknown x_axis_type: %s" % x_axis_type) result = integrate(tout, c0, parameters, **(integrate_kwargs or {})) sources = [ ColumnDataSource( data={ "tout": to_unitless(result.xout, output_time_unit), k: to_unitless(result.yout[:, idx], output_conc_unit), }) for idx, k in enumerate(rsys.substances) ] if fig_kwargs is None: Cmax = np.max(result.yout) x_range = list( to_unitless([result.xout[0], result.xout[-1]], output_time_unit)) y_range = list(to_unitless([Cmax * 0, Cmax * 1.1], output_conc_unit)) fig_kwargs = dict( plot_height=400, plot_width=400, title="C vs t", tools="crosshair,pan,reset,save,wheel_zoom", x_range=x_range, y_range=y_range, x_axis_type=x_axis_type, y_axis_type=y_axis_type, ) plot = Figure(**fig_kwargs) colors = "red green blue black cyan magenta".split() for idx, k in enumerate(rsys.substances): plot.line( "tout", k, source=sources[idx], line_width=3, line_alpha=0.6, color=colors[idx % len(colors)], ) def _C(k): return to_unitless(c0[k], output_conc_unit) if p_units is None: p_units = [None] * len(param_keys) p_ul = [ to_unitless(parameters[k], _u) for k, _u in zip(param_keys, p_units) ] def _dict_to_unitless(d, u): return {k: to_unitless(v, u) for k, v in d.items()} c0_widgets = OrderedDict() for k in rsys.substances: if conc_bounds is not None and k in conc_bounds: if k in slider_kwargs: raise ValueError( "Key '%s' both in slider_kwargs and conc_bounds" % k) slider_defaults = _dict_to_unitless(conc_bounds[k], output_conc_unit) else: ck = _C(k) if ck == 0: max_ = max(*[_C(k) for k in rsys.substances]) slider_defaults = dict(start=0, end=max_, step=max_ / 100) else: slider_defaults = dict(start=_C(k) / 2, end=_C(k) * 2, step=_C(k) / 10) c0_widgets[k] = Slider( title=(k + " / " + output_conc_unit.dimensionality.unicode) if hasattr(output_conc_unit, "dimensionality") else k, value=_C(k), **slider_kwargs.get(k, slider_defaults)) param_widgets = OrderedDict([( k, Slider(title=k if u is None else k + " / " + u.dimensionality.unicode, value=v, **_dict_to_unitless( slider_kwargs.get( k, dict(start=v / 10, end=v * 10, step=v / 10)), u, )), ) for k, v, u in zip(param_keys, p_ul, p_units)]) all_widgets = list(chain(param_widgets.values(), c0_widgets.values())) def update_data(attrname, old, new): _c0 = defaultdict(lambda: 0 * output_conc_unit) for k, w in c0_widgets.items(): _c0[k] = w.value * output_conc_unit _params = {} for (k, w), u in zip(param_widgets.items(), p_units): _params[k] = w.value if u is None else w.value * u _result = integrate(tout, _c0, _params) for idx, k in enumerate(rsys.substances): sources[idx].data = { "tout": to_unitless(_result.xout, output_time_unit), k: to_unitless(_result.yout[:, idx], output_conc_unit), } for w in all_widgets: w.on_change("value", update_data) inputs = Column(children=all_widgets) return Row(children=[inputs, plot], width=800)
'indices': {} } } source2.selected = { '0d': { 'flag': False, 'indices': [] }, '1d': { 'indices': [] }, '2d': { 'indices': {} } } reset.on_click(on_reset_click) widgetBox = WidgetBox(children=[reset], width=150) row = Row(children=[widgetBox, plot1, plot2]) document = curdoc() document.add_root(row) if __name__ == "__main__": print("\npress ctrl-C to exit") session = push_session(document) session.show() session.loop_until_closed()