def trigger_update(self): self.state = profile.get_profile(self.log, start=self.start, stop=self.stop) data = profile.plot_data(self.state, profile_interval) self.states = data.pop("states") update(self.source, data) times = [t * 1000 for t, _ in self.log] counts = list(toolz.pluck("count", toolz.pluck(1, self.log))) self.ts_source.data.update({"time": times, "count": counts})
def __init__(self, server, doc=None, **kwargs): if doc is not None: self.doc = weakref.ref(doc) self.server = server self.log = self.server.io_loop.profile self.start = None self.stop = None self.ts = {"count": [], "time": []} self.state = profile.get_profile(self.log) data = profile.plot_data(self.state, profile_interval) self.states = data.pop("states") self.profile_plot, self.source = profile.plot_figure(data, **kwargs) changing = [False] # avoid repeated changes from within callback @without_property_validation def cb(attr, old, new): if changing[0]: return with log_errors(): if isinstance(new, list): # bokeh >= 1.0 selected = new else: selected = new["1d"]["indices"] try: ind = selected[0] except IndexError: return data = profile.plot_data(self.states[ind], profile_interval) del self.states[:] self.states.extend(data.pop("states")) changing[0] = True # don't recursively trigger callback update(self.source, data) if isinstance(new, list): # bokeh >= 1.0 self.source.selected.indices = old else: self.source.selected = old changing[0] = False if BOKEH_VERSION >= "1.0.0": self.source.selected.on_change("indices", cb) else: self.source.on_change("selected", cb) self.ts_source = ColumnDataSource({"time": [], "count": []}) self.ts_plot = figure( title="Activity over time", height=150, x_axis_type="datetime", active_drag="xbox_select", tools="xpan,xwheel_zoom,xbox_select,reset", sizing_mode="stretch_width", toolbar_location="above", ) self.ts_plot.line("time", "count", source=self.ts_source) self.ts_plot.circle( "time", "count", source=self.ts_source, color=None, selection_color="orange" ) self.ts_plot.yaxis.visible = False self.ts_plot.grid.visible = False def ts_change(attr, old, new): with log_errors(): try: selected = self.ts_source.selected.indices except AttributeError: selected = self.ts_source.selected["1d"]["indices"] if selected: start = self.ts_source.data["time"][min(selected)] / 1000 stop = self.ts_source.data["time"][max(selected)] / 1000 self.start, self.stop = min(start, stop), max(start, stop) else: self.start = self.stop = None self.trigger_update() if BOKEH_VERSION >= "1.0.0": self.ts_source.selected.on_change("indices", ts_change) else: self.ts_source.on_change("selected", ts_change) self.reset_button = Button(label="Reset", button_type="success") self.reset_button.on_click(lambda: self.update(self.state)) self.update_button = Button(label="Update", button_type="success") self.update_button.on_click(self.trigger_update) self.root = column( row(self.reset_button, self.update_button, sizing_mode="scale_width"), self.profile_plot, self.ts_plot, **kwargs )