def test_init_with_int(self): datarange1d = DataRange1d(start=-1, end=3) assert datarange1d.start == -1 assert datarange1d.end == 3 assert datarange1d.bounds is None
module.exports = { Model: MyRow View: MyRowView } """ source = ColumnDataSource( data=dict(x=[1, 2, 3, 4, 4, 5, 5], y=[5, 4, 3, 2, 2.1, 1, 1.1], color=[ "rgb(0, 100, 120)", "green", "blue", "#2c7fb8", "#2c7fb8", "rgba(120, 230, 150, 0.5)", "rgba(120, 230, 150, 0.5)" ])) xdr = DataRange1d() ydr = DataRange1d() plot = Plot(x_range=xdr, y_range=ydr) circle = Circle(x="x", y="y", radius=0.2, fill_color="color", line_color="black") circle_renderer = plot.add_glyph(source, circle) plot.add_layout(LinearAxis(), 'below') plot.add_layout(LinearAxis(), 'left') tap = TapTool(renderers=[circle_renderer],
t0 = sprint.Time[0] sprint["Abbrev"] = sprint.Country sprint["Country"] = sprint.Abbrev.map(lambda abbr: abbrev_to_country[abbr]) sprint["Medal"] = sprint.Medal.map(lambda medal: medal.lower()) sprint["Speed"] = 100.0/sprint.Time sprint["MetersBack"] = 100.0*(1.0 - t0/sprint.Time) sprint["MedalFill"] = sprint.Medal.map(lambda medal: fill_color[medal]) sprint["MedalLine"] = sprint.Medal.map(lambda medal: line_color[medal]) sprint["SelectedName"] = sprint[["Name", "Medal", "Year"]].apply(tuple, axis=1).map(lambda args: selected_name(*args)) source = ColumnDataSource(sprint) xdr = Range1d(start=sprint.MetersBack.max()+2, end=0) # XXX: +2 is poor-man's padding (otherwise misses last tick) ydr = DataRange1d(range_padding=4, range_padding_units="absolute") plot = figure( x_range=xdr, y_range=ydr, plot_width=1000, plot_height=600, toolbar_location=None, outline_line_color=None, y_axis_type=None) plot.title.text = "Usain Bolt vs. 116 years of Olympic sprinters" plot.title.text_font_size = "19px" plot.xaxis.ticker = SingleIntervalTicker(interval=5, num_minor_ticks=0) plot.xaxis.axis_line_color = None plot.xaxis.major_tick_line_color = None plot.xgrid.grid_line_dash = "dashed"
assert isinstance(r, Range1d) assert r.start == 1.2 assert r.end == 10 def test_with_pandas_group(self, pd) -> None: from bokeh.sampledata.iris import flowers g = flowers.groupby('species') r = bpp.get_range(g) assert isinstance(r, FactorRange) assert r.factors == ['setosa', 'versicolor', 'virginica'] # should always be sorted #----------------------------------------------------------------------------- # Private API #----------------------------------------------------------------------------- _RANGES = [Range1d(), DataRange1d(), FactorRange()] class Test__get_axis_class: @pytest.mark.parametrize('range', _RANGES) def test_axis_type_None(self, range) -> None: assert(bpp._get_axis_class(None, range, 0)) == (None, {}) assert(bpp._get_axis_class(None, range, 1)) == (None, {}) @pytest.mark.parametrize('range', _RANGES) def test_axis_type_linear(self, range) -> None: assert(bpp._get_axis_class("linear", range, 0)) == (LinearAxis, {}) assert(bpp._get_axis_class("linear", range, 1)) == (LinearAxis, {}) @pytest.mark.parametrize('range', _RANGES) def test_axis_type_log(self, range) -> None:
def large_plot(n): from bokeh.models import (Plot, LinearAxis, Grid, GlyphRenderer, ColumnDataSource, DataRange1d, PanTool, ZoomInTool, ZoomOutTool, WheelZoomTool, BoxZoomTool, BoxSelectTool, SaveTool, ResetTool) from bokeh.models.layouts import Column from bokeh.models.glyphs import Line col = Column() objects = set([col]) for i in xrange(n): source = ColumnDataSource(data=dict(x=[0, i + 1], y=[0, i + 1])) xdr = DataRange1d() ydr = DataRange1d() plot = Plot(x_range=xdr, y_range=ydr) xaxis = LinearAxis(plot=plot) yaxis = LinearAxis(plot=plot) xgrid = Grid(plot=plot, dimension=0) ygrid = Grid(plot=plot, dimension=1) tickers = [ xaxis.ticker, xaxis.formatter, yaxis.ticker, yaxis.formatter ] glyph = Line(x='x', y='y') renderer = GlyphRenderer(data_source=source, glyph=glyph) plot.renderers.append(renderer) pan = PanTool() zoom_in = ZoomInTool() zoom_out = ZoomOutTool() wheel_zoom = WheelZoomTool() box_zoom = BoxZoomTool() box_select = BoxSelectTool() save = SaveTool() reset = ResetTool() tools = [ pan, zoom_in, zoom_out, wheel_zoom, box_zoom, box_select, save, reset ] plot.add_tools(*tools) col.children.append(plot) objects |= set([ xdr, ydr, xaxis, yaxis, xgrid, ygrid, renderer, renderer.view, glyph, source, source.selected, source.selection_policy, plot, plot.x_scale, plot.y_scale, plot.toolbar, plot.title, box_zoom.overlay, box_select.overlay, ] + tickers + tools) return col, objects
def plot_forest( ax, datasets, var_names, model_names, combined, colors, figsize, width_ratios, linewidth, markersize, kind, ncols, hdi_prob, quartiles, rope, ridgeplot_overlap, ridgeplot_alpha, ridgeplot_kind, ridgeplot_truncate, ridgeplot_quantiles, textsize, ess, r_hat, backend_config, backend_kwargs, show, ): """Bokeh forest plot.""" plot_handler = PlotHandler(datasets, var_names=var_names, model_names=model_names, combined=combined, colors=colors) if figsize is None: if kind == "ridgeplot": figsize = (min(14, sum(width_ratios) * 3), plot_handler.fig_height() * 3) else: figsize = (min(12, sum(width_ratios) * 2), plot_handler.fig_height()) (figsize, _, _, _, auto_linewidth, auto_markersize) = _scale_fig_size(figsize, textsize, 1.1, 1) if linewidth is None: linewidth = auto_linewidth if markersize is None: markersize = auto_markersize if backend_config is None: backend_config = {} backend_config = { **backend_kwarg_defaults( ("bounds_x_range", "plot.bokeh.bounds_x_range"), ("bounds_y_range", "plot.bokeh.bounds_y_range"), ), **backend_config, } if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults(("dpi", "plot.bokeh.figure.dpi"), ), **backend_kwargs, } dpi = backend_kwargs.pop("dpi") if ax is None: axes = [] for i, width_r in zip(range(ncols), width_ratios): backend_kwargs_i = backend_kwargs.copy() backend_kwargs_i.setdefault("width", int(figsize[0] * dpi)) backend_kwargs_i.setdefault( "height", int(figsize[1] * (width_r / sum(width_ratios)) * dpi * 1.25)) if i == 0: ax = bkp.figure(**backend_kwargs_i, ) backend_kwargs_i.setdefault("y_range", ax.y_range) else: ax = bkp.figure(**backend_kwargs_i) axes.append(ax) else: axes = ax axes = np.atleast_2d(axes) if kind == "forestplot": plot_handler.forestplot( hdi_prob, quartiles, linewidth, markersize, axes[0, 0], rope, ) elif kind == "ridgeplot": plot_handler.ridgeplot( hdi_prob, ridgeplot_overlap, linewidth, markersize, ridgeplot_alpha, ridgeplot_kind, ridgeplot_truncate, ridgeplot_quantiles, axes[0, 0], ) else: raise TypeError("Argument 'kind' must be one of 'forestplot' or " "'ridgeplot' (you provided {})".format(kind)) idx = 1 if ess: plot_handler.plot_neff(axes[0, idx], markersize) idx += 1 if r_hat: plot_handler.plot_rhat(axes[0, idx], markersize) idx += 1 for i, ax_ in enumerate(axes.ravel()): if kind == "ridgeplot": ax_.xgrid.grid_line_color = None ax_.ygrid.grid_line_color = None else: ax_.ygrid.grid_line_color = None if i != 0: ax_.yaxis.visible = False ax_.outline_line_color = None ax_.x_range = DataRange1d(bounds=backend_config["bounds_x_range"], min_interval=1) ax_.y_range = DataRange1d(bounds=backend_config["bounds_y_range"], min_interval=2) labels, ticks = plot_handler.labels_and_ticks() axes[0, 0].yaxis.ticker = FixedTicker(ticks=ticks) axes[0, 0].yaxis.major_label_overrides = dict( zip(map(str, ticks), map(str, labels))) all_plotters = list(plot_handler.plotters.values()) y_max = plot_handler.y_max() - all_plotters[-1].group_offset if kind == "ridgeplot": # space at the top y_max += ridgeplot_overlap axes[0, 0].y_range._property_values["start"] = -all_plotters[ # pylint: disable=protected-access 0].group_offset axes[0, 0].y_range._property_values["end"] = y_max # pylint: disable=protected-access show_layout(axes, show) return axes
N = 9 x = np.linspace(-2, 2, N) y = x**2 source = ColumnDataSource(dict( x=x, y=y, xp02=x+0.4, xp01=x+0.1, xm01=x-0.1, yp01=y+0.2, ym01=y-0.2, ) ) xdr = DataRange1d(sources=[source.columns("x")]) ydr = DataRange1d(sources=[source.columns("y")]) plot = Plot( title=None, x_range=xdr, y_range=ydr, plot_width=300, plot_height=300, h_symmetry=False, v_symmetry=False, min_border=0, toolbar_location=None) glyph = Bezier(x0="x", y0="y", x1="xp02", y1="y", cx0="xp01", cy0="yp01", cx1="xm01", cy1="ym01", line_color="#D95F02", line_width=2) plot.add_glyph(source, glyph) xaxis = LinearAxis() plot.add_layout(xaxis, 'below') yaxis = LinearAxis() plot.add_layout(yaxis, 'left')
def task_stream_figure(clear_interval='20s', **kwargs): """ kwargs are applied to the bokeh.models.plots.Plot constructor """ clear_interval = parse_timedelta(clear_interval, default='ms') source = ColumnDataSource(data=dict(start=[time() - clear_interval], duration=[0.1], key=['start'], name=['start'], color=['white'], duration_text=['100 ms'], worker=['foo'], y=[0], worker_thread=[1], alpha=[0.0])) x_range = DataRange1d(range_padding=0) y_range = DataRange1d(range_padding=0) root = figure(name='task_stream', title="Task Stream", id='bk-task-stream-plot', x_range=x_range, y_range=y_range, toolbar_location="above", x_axis_type='datetime', min_border_right=35, tools='', **kwargs) rect = root.rect(source=source, x="start", y="y", width="duration", height=0.4, fill_color="color", line_color="color", line_alpha=0.6, fill_alpha="alpha", line_width=3) rect.nonselection_glyph = None root.yaxis.major_label_text_alpha = 0 root.yaxis.minor_tick_line_alpha = 0 root.yaxis.major_tick_line_alpha = 0 root.xgrid.visible = False hover = HoverTool(point_policy="follow_mouse", tooltips=""" <div> <span style="font-size: 12px; font-weight: bold;">@name:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@duration_text</span> </div> """) tap = TapTool(callback=OpenURL(url='/profile?key=@name')) root.add_tools(hover, tap, BoxZoomTool(), ResetTool(), PanTool(dimensions="width"), WheelZoomTool(dimensions="width")) if ExportTool: export = ExportTool() export.register_plot(root) root.add_tools(export) return source, root
def __init__(self, worker, height=300, **kwargs): with log_errors(): self.worker = worker names = [ "start", "stop", "middle", "duration", "who", "y", "hover", "alpha", "bandwidth", "total", ] self.incoming = ColumnDataSource({name: [] for name in names}) self.outgoing = ColumnDataSource({name: [] for name in names}) x_range = DataRange1d(range_padding=0) y_range = DataRange1d(range_padding=0) fig = figure( title="Peer Communications", x_axis_type="datetime", x_range=x_range, y_range=y_range, height=height, tools="", **kwargs, ) fig.rect( source=self.incoming, x="middle", y="y", width="duration", height=0.9, color="red", alpha="alpha", ) fig.rect( source=self.outgoing, x="middle", y="y", width="duration", height=0.9, color="blue", alpha="alpha", ) hover = HoverTool(point_policy="follow_mouse", tooltips="""@hover""") fig.add_tools( hover, ResetTool(), PanTool(dimensions="width"), WheelZoomTool(dimensions="width"), ) self.root = fig self.last_incoming = 0 self.last_outgoing = 0 self.who = dict()
def app(doc, hist_storage_, data_storage_, freq_storage_, depolarizer, names): # вспомогательные глобальные data_source = ColumnDataSource({key: [] for key in names}) fit_handler = { "fit_line": None, "input_fields": {}, "fit_indices": tuple() } utc_plus_7h = 7 * 3600 time_coef = 10**3 # Пересчёт времени в мс для формата datetime Bokeh fit_line_points_amount = 300 # Количество точек для отрисовки подгоночной кривой depol_list = [] datetime_formatter = DatetimeTickFormatter( milliseconds=['%M:%S:%3Nms'], seconds=['%H:%M:%S'], minsec=['%H:%M:%S'], minutes=['%H:%M:%S'], hourmin=['%H:%M:%S'], hours=['%H:%M:%S'], days=["%d.%m"], months=["%Y-%m-%d"], ) # Гистограмма пятна img, img_x_std, img_y_std = hist_storage_.get_hist_with_std() hist_source = ColumnDataSource(data=dict(image=[img])) width_ = config.GEM_X * 5 hist_height_ = config.GEM_Y * 5 hist_fig = figure(plot_width=width_, plot_height=hist_height_, x_range=(0, config.GEM_X), y_range=(0, config.GEM_Y)) hist_fig.image(image='image', x=0, y=0, dw=config.GEM_X, dh=config.GEM_Y, palette="Spectral11", source=hist_source) hist_label = Label( x=0, y=0, x_units='screen', y_units='screen', text=f"x_std={'%.2f' % img_x_std},y_std={'%.2f' % img_y_std}", render_mode='css', border_line_color='black', border_line_alpha=1.0, background_fill_color='white', background_fill_alpha=1.0) hist_fig.add_layout(hist_label) hist_buffer_len = config.hist_buffer_len - 1 hist_slider = RangeSlider(start=0, end=hist_buffer_len, value=(0, hist_buffer_len), step=1, title="Срез пятна (от..до) сек назад") def hist_update(): img, img_x_std, img_y_std = hist_storage_.get_hist_with_std( hist_buffer_len - hist_slider.value[1], hist_buffer_len - hist_slider.value[0]) hist_label.text = f"x_std={'%.2f' % img_x_std},y_std={'%.2f' % img_y_std}" hist_source.data = {'image': [img]} # График асимметрии asym_fig = figure( plot_width=width_, plot_height=400, tools="box_zoom, xbox_select, wheel_zoom, pan, save, reset", active_scroll="wheel_zoom", active_drag="pan", toolbar_location="below", lod_threshold=100, x_axis_location=None, x_range=DataRange1d()) asym_fig.yaxis.axis_label = "мм" asym_fig.extra_x_ranges = { "time_range": asym_fig.x_range, "depolarizer": asym_fig.x_range, "sec": asym_fig.x_range } depol_axis = LinearAxis(x_range_name="depolarizer", axis_label='Деполяризатор', major_label_overrides={}, major_label_orientation=pi / 2) asym_fig.add_layout( LinearAxis(x_range_name="time_range", axis_label='Время', formatter=datetime_formatter), 'below') # Прямая, с которой идёт отсчёт времени для подгонки zone_of_interest = Span(location=0, dimension='height', line_color='green', line_dash='dashed', line_width=3) sec_axis = LinearAxis( x_range_name='sec', axis_label='Секунды') # Секундная ось сверху (настр. диапазон) sec_axis.formatter = FuncTickFormatter( code= f"return ((tick - {zone_of_interest.location}) / {time_coef}).toFixed(1);" ) def double_tap(event): """Двойной клик для перемещения отсчёта времени для подгонки""" zone_of_interest.location = event.x sec_axis.formatter = FuncTickFormatter( code=f"return ((tick - {event.x}) / {time_coef}).toFixed(1);") asym_fig.add_layout(depol_axis, 'below') asym_fig.add_layout(sec_axis, 'above') asym_fig.add_layout(zone_of_interest) asym_fig.on_event(DoubleTap, double_tap) def draw_selected_area(attr, old, new): """Подсветка выделенной для подгонки области""" # Удаляет предыдущую выделенную область asym_fig.renderers = [ r for r in asym_fig.renderers if r.name != 'fit_zone' ] if not new.indices: fit_handler["fit_indices"] = tuple() return l_time_ = data_source.data['time'][min(new.indices)] r_time_ = data_source.data['time'][max(new.indices)] if l_time_ != r_time_: fit_handler["fit_indices"] = (l_time_, r_time_) box_select = BoxAnnotation(left=l_time_, right=r_time_, name="fit_zone", fill_alpha=0.1, fill_color='red') asym_fig.add_layout(box_select) asym_box_select_overlay = asym_fig.select_one(BoxSelectTool).overlay asym_box_select_overlay.line_color = "firebrick" data_source.on_change('selected', draw_selected_area) def create_whisker(data_name: str): """ Создает усы для data_name от time :param data_name: имя поля данных из data_storage (у данных должны быть поля '_up_error', '_down_error') :return: Bokeh Whisker """ return Whisker(source=data_source, base="time", upper=data_name + "_up_error", lower=data_name + "_down_error") def create_render(data_name: str, glyph: str, color: str): """ Рисует data_name от time :param data_name: имя поля данных из data_storage :param glyph: ['circle', 'square'] :param color: цвет :return: Bokeh fig """ if glyph == 'circle': func = asym_fig.circle elif glyph == 'square': func = asym_fig.square else: raise ValueError('Неверное значение glyph') return func('time', data_name, source=data_source, name=data_name, color=color, nonselection_alpha=1, nonselection_color=color) # Список линий на графике асимметрии: data_name, name, glyph, color asym_renders_name = [('y_one_asym', 'ΔY ONE', 'circle', 'black'), ('y_cog_asym', 'ΔY COG', 'circle', 'green'), ('x_one_asym', 'ΔX ONE', 'square', 'black'), ('x_cog_asym', 'ΔX COG', 'square', 'green')] pretty_names = dict([(data_name, name) for data_name, name, *_ in asym_renders_name]) asym_renders = [ create_render(data_name, glyph, color) for data_name, _, glyph, color in asym_renders_name ] asym_error_renders = [ create_whisker(data_name) for data_name, *_ in asym_renders_name ] for render, render_error in zip(asym_renders, asym_error_renders): asym_fig.add_layout(render_error) render.js_on_change( 'visible', CustomJS(args=dict(x=render_error), code="x.visible = cb_obj.visible")) asym_fig.add_layout( Legend(items=[(pretty_names[r.name], [r]) for r in asym_renders], click_policy="hide", location="top_left", background_fill_alpha=0.2, orientation="horizontal")) # Вывод информации о точке при наведении мыши asym_fig.add_tools( HoverTool( renderers=asym_renders, formatters={"time": "datetime"}, mode='vline', tooltips=[ ("Время", "@time{%F %T}"), *[(pretty_names[r.name], f"@{r.name}{'{0.000}'} ± @{r.name + '_error'}{'{0.000}'}") for r in asym_renders], ("Деполяризатор", f"@depol_energy{'{0.000}'}") ])) # Окно ввода периода усреднения period_input = TextInput(value='300', title="Время усреднения (с):") # Глобальный список параметров, для сохранения результатов запросов к data_storage params = {'last_time': 0, 'period': int(period_input.value)} def update_data(): """ Обновляет данные для пользовательского интерфейса, собирая их у data_storage """ if params['period'] != int(period_input.value): data_source.data = {name: [] for name in names} params['period'] = int(period_input.value) params['last_time'] = 0 depol_axis.ticker = [] depol_axis.major_label_overrides.clear() depol_list.clear() points, params['last_time'] = data_storage_.get_mean_from( params['last_time'], params['period']) if not points['time']: return points['time'] = [(i + utc_plus_7h) * time_coef for i in points['time'] ] # Учёт сдвижки UTC+7 для отрисовки for time, energy in zip(points['time'], points['depol_energy']): if energy == 0: continue depol_axis.major_label_overrides[time] = str(energy) depol_list.append(time) depol_axis.ticker = depol_list # TODO: оптимизировать data_source.stream({key: np.array(val) for key, val in points.items()}, rollover=250) def period_correction_func(attr, old, new): """Проверка введенного значения на целое число больше нуля""" if not new.isdigit() or int(new) <= 0: period_input.value = old period_input.on_change('value', period_correction_func) # Создание панели графиков (вкладок) def create_fig(data_names: list, colors: list, y_axis_name: str, ers: str = None): """Создаёт график data_names : time. Если в data_names несколько имён, то они будут на одном графике. Возвращает fig. :param data_names: список с именами полей данных из data_storage :param colors: список цветов, соотв. элементам из fig_names :param y_axis_name: имя оси Y :param ers: 'err', 'pretty' --- вид усов (у данных должны быть поля '_up_error', '_down_error'), 'err' --- усы обыкновенные 'pretty' --- усы без шляпки и цветом совпадающим с цветом точки :return fig --- Bokeh figure """ if len(data_names) != len(colors): raise IndexError('Кол-во цветов и графиков не совпадает') fig = figure(plot_width=width_, plot_height=300, tools="box_zoom, wheel_zoom, pan, save, reset", active_scroll="wheel_zoom", lod_threshold=100, x_axis_type="datetime") for fig_name, color in zip(data_names, colors): if ers == 'err': fig.add_layout( Whisker(source=data_source, base="time", upper=fig_name + '_up_error', lower=fig_name + '_down_error')) elif ers == 'pretty': fig.add_layout( Whisker(source=data_source, base="time", upper=fig_name + '_up_error', lower=fig_name + '_down_error', line_color=color, lower_head=None, upper_head=None)) fig.circle('time', fig_name, source=data_source, size=5, color=color, nonselection_alpha=1, nonselection_color=color) fig.yaxis.axis_label = y_axis_name fig.xaxis.axis_label = 'Время' fig.xaxis.formatter = datetime_formatter fig.x_range = asym_fig.x_range return fig figs = [(create_fig(['y_one_l'], ['black'], 'Y [мм]', 'err'), 'Y ONE L'), (create_fig(['y_one_r'], ['black'], 'Y [мм]', 'err'), 'Y ONE R'), (create_fig(['y_cog_l'], ['black'], 'Y [мм]', 'err'), 'Y COG L'), (create_fig(['y_cog_r'], ['black'], 'Y [мм]', 'err'), 'Y COG R'), (create_fig(['rate' + i for i in ['_l', '_r']], ['red', 'blue'], 'Усл. ед.', 'pretty'), 'Rate'), (create_fig(['corrected_rate' + i for i in ['_l', '_r']], ['red', 'blue'], 'Усл. ед.', 'pretty'), 'Corr. rate'), (create_fig(['delta_rate'], ['black'], 'Корр. лев. - корр. пр.', 'err'), 'Delta corr. rate'), (create_fig(['charge'], ['blue'], 'Ед.'), 'Charge')] tab_handler = Tabs( tabs=[Panel(child=fig, title=fig_name) for fig, fig_name in figs], width=width_) # Окно статуса деполяризатора depol_status_window = Div(text="Инициализация...", width=500, height=500) depol_start_stop_buttons = RadioButtonGroup( labels=["Старт", "Стоп"], active=(0 if depolarizer.is_scan else 1)) fake_depol_button = Button(label="Деполяризовать", width=200) fake_depol_button.on_click(GEM.depolarize) depol_input_harmonic_number = TextInput(value=str( '%.1f' % depolarizer.harmonic_number), title=f"Номер гармоники", width=150) depol_input_attenuation = TextInput(value=str('%.1f' % depolarizer.attenuation), title=f"Аттенюатор (дБ)", width=150) depol_input_speed = TextInput( value=str(depolarizer.frequency_to_energy(depolarizer.speed, n=0)), title=f"Скорость ({'%.1f' % depolarizer.speed} Гц):", width=150) depol_input_step = TextInput( value=str(depolarizer.frequency_to_energy(depolarizer.step, n=0)), title=f"Шаг ({'%.1f' % depolarizer.step} Гц):", width=150) depol_input_initial = TextInput( value=str(depolarizer.frequency_to_energy(depolarizer.initial)), title=f"Начало ({'%.1f' % depolarizer.initial} Гц):", width=150) depol_input_final = TextInput( value=str(depolarizer.frequency_to_energy(depolarizer.final)), title=f"Конец ({'%.1f' % depolarizer.final} Гц):", width=150) depol_dict = { "speed": (depol_input_speed, depolarizer.set_speed), "step": (depol_input_step, depolarizer.set_step), "initial": (depol_input_initial, depolarizer.set_initial), "final": (depol_input_final, depolarizer.set_final), "harmonic_number": (depol_input_harmonic_number, depolarizer.set_harmonic_number), "attenuation": (depol_input_attenuation, depolarizer.set_attenuation) } def change_value_generator(value_name): """Возвращает callback функцию для параметра value_name деполяризатора""" def change_value(attr, old, new): if float(old) == float(new): return depol_input, depol_set = depol_dict[value_name] depol_current = depolarizer.get_by_name(value_name) try: if value_name in ['harmonic_number', 'attenuation']: new_val = float(new) elif value_name in ['speed', 'step']: new_val = depolarizer.energy_to_frequency(float(new), n=0) else: new_val = depolarizer.energy_to_frequency(float(new)) if depol_current == new_val: return depol_set(new_val) if value_name not in ['harmonic_number', 'attenuation']: name = depol_input.title.split(' ')[0] depol_input.title = name + f" ({'%.1f' % new_val} Гц):" except ValueError as e: if value_name in ['harmonic_number', 'attenuation']: depol_input.value = str(depol_current) elif value_name in ['speed', 'step']: depol_input.value = str( depolarizer.frequency_to_energy(depol_current, n=0)) else: depol_input.value = str( depolarizer.frequency_to_energy(depol_current)) print(e) return change_value depol_input_harmonic_number.on_change( 'value', change_value_generator('harmonic_number')) depol_input_attenuation.on_change('value', change_value_generator("attenuation")) depol_input_speed.on_change('value', change_value_generator("speed")) depol_input_step.on_change('value', change_value_generator("step")) depol_input_initial.on_change('value', change_value_generator("initial")) depol_input_final.on_change('value', change_value_generator("final")) def update_depol_status( ): # TODO: самому пересчитывать начало и конец сканирования по частотам """Обновляет статус деполяризатора, если какое-то значение поменялось другим пользователем""" depol_start_stop_buttons.active = 0 if depolarizer.is_scan else 1 depol_status_window.text = f""" <p>Сканирование: <font color={'"green">включено' if depolarizer.is_scan else '"red">выключено'}</font></p> <p/>Частота {"%.1f" % depolarizer.current_frequency} (Гц)</p> <p/>Энергия {"%.3f" % depolarizer.current_energy} МэВ</p>""" for value_name in ['speed', 'step']: depol_input, _ = depol_dict[value_name] depol_value = depolarizer.frequency_to_energy( depolarizer.get_by_name(value_name), n=0) if float(depol_input.value) != depol_value: depol_input.value = str(depol_value) for value_name in ['initial', 'final']: depol_input, _ = depol_dict[value_name] freq = depolarizer.get_by_name(value_name) energy = depolarizer.frequency_to_energy(freq) if float(depol_input.value) != energy: depol_input.value = str(energy) else: name = depol_input.title.split(' ')[0] depol_input.title = name + f" ({'%.1f' % freq} Гц):" for value_name in ['attenuation', 'harmonic_number']: depol_input, _ = depol_dict[value_name] depol_value = depolarizer.get_by_name(value_name) if float(depol_input.value) != depol_value: depol_input.value = str(int(depol_value)) depol_start_stop_buttons.on_change( "active", lambda attr, old, new: (depolarizer.start_scan() if new == 0 else depolarizer.stop_scan())) # Подгонка fit_line_selection_widget = Select(title="Fitting line:", width=200, value=asym_renders[0].name, options=[(render.name, pretty_names[render.name]) for render in asym_renders]) options = [name for name in fit.function_handler.keys()] if not options: raise IndexError("Пустой function_handler в fit.py") fit_function_selection_widget = Select(title="Fitting function:", value=options[0], options=options, width=200) fit_button = Button(label="FIT", width=200) def make_parameters_table(): """Создание поля ввода данных для подгонки: начальное значение, fix и т.д.""" name = fit_function_selection_widget.value t_width = 10 t_height = 12 rows = [ row(Paragraph(text="name", width=t_width, height=t_height), Paragraph(text="Fix", width=t_width, height=t_height), Paragraph(text="Init value", width=t_width, height=t_height), Paragraph(text="step (error)", width=t_width, height=t_height), Paragraph(text="limits", width=t_width, height=t_height), Paragraph(text="lower_limit", width=t_width, height=t_height), Paragraph(text="upper_limit", width=t_width, height=t_height)) ] fit_handler["input_fields"] = {} for param, value in fit.get_function_params(name): fit_handler["input_fields"][param] = {} fit_handler["input_fields"][param]["fix"] = CheckboxGroup( labels=[""], width=t_width, height=t_height) fit_handler["input_fields"][param]["Init value"] = TextInput( width=t_width, height=t_height, value=str(value)) fit_handler["input_fields"][param]["step (error)"] = TextInput( width=t_width, height=t_height, value='1') fit_handler["input_fields"][param]["limits"] = CheckboxGroup( labels=[""], width=t_width, height=t_height) fit_handler["input_fields"][param]["lower_limit"] = TextInput( width=t_width, height=t_height) fit_handler["input_fields"][param]["upper_limit"] = TextInput( width=t_width, height=t_height) rows.append( row(Paragraph(text=param, width=t_width, height=t_height), fit_handler["input_fields"][param]["fix"], fit_handler["input_fields"][param]["Init value"], fit_handler["input_fields"][param]["step (error)"], fit_handler["input_fields"][param]["limits"], fit_handler["input_fields"][param]["lower_limit"], fit_handler["input_fields"][param]["upper_limit"])) return column(rows) def clear_fit(): """Удаление подогнанной кривой""" if fit_handler["fit_line"] in asym_fig.renderers: asym_fig.renderers.remove(fit_handler["fit_line"]) energy_window = Div(text="Частота: , энергия: ") clear_fit_button = Button(label="Clear", width=200) clear_fit_button.on_click(clear_fit) def fit_callback(): if not fit_handler["fit_indices"]: return name = fit_function_selection_widget.value line_name = fit_line_selection_widget.value left_time_, right_time_ = fit_handler["fit_indices"] left_ind_ = bisect.bisect_left(data_source.data['time'], left_time_) right_ind_ = bisect.bisect_right(data_source.data['time'], right_time_, lo=left_ind_) if left_ind_ == right_ind_: return clear_fit() x_axis = data_source.data['time'][left_ind_:right_ind_] y_axis = data_source.data[line_name][left_ind_:right_ind_] y_errors = data_source.data[line_name + '_up_error'][left_ind_:right_ind_] - y_axis init_vals = { name: float(val["Init value"].value) for name, val in fit_handler["input_fields"].items() } steps = { "error_" + name: float(val["step (error)"].value) for name, val in fit_handler["input_fields"].items() } fix_vals = { "fix_" + name: True for name, val in fit_handler["input_fields"].items() if val["fix"].active } limit_vals = { "limit_" + name: (float(val["lower_limit"].value), float(val["upper_limit"].value)) for name, val in fit_handler["input_fields"].items() if val["limits"].active } kwargs = {} kwargs.update(init_vals) kwargs.update(steps) kwargs.update(fix_vals) kwargs.update(limit_vals) # Предобработка времени, перевод в секунды, вычитание сдвига (для лучшей подгонки) left_ = zone_of_interest.location x_time = x_axis - left_ # Привёл время в интервал от 0 x_time /= time_coef # Перевёл в секунды # Создание точек, которые передадутся в подогнанную функцию с параметрами, # и точек, которые соответсвуют реальным временам на графике (т.е. без смещения к 0) fit_line_real_x_axis = np.linspace(left_time_, right_time_, fit_line_points_amount) fit_line_x_axis = fit_line_real_x_axis - left_ fit_line_x_axis /= time_coef m = fit.create_fit_func(name, x_time, y_axis, y_errors, kwargs) fit.fit(m) params_ = m.get_param_states() for param in params_: fit_handler["input_fields"][ param['name']]["Init value"].value = "%.3f" % param['value'] fit_handler["input_fields"][ param['name']]["step (error)"].value = "%.3f" % param['error'] if param['name'] == "depol_time": freq = freq_storage_.find_closest_freq(param['value'] + left_ / time_coef - utc_plus_7h) freq_error = abs(depolarizer.speed * param['error']) energy = depolarizer.frequency_to_energy( freq) if freq != 0 else 0 energy_error = depolarizer.frequency_to_energy( freq_error, depolarizer._F0, 0) energy_window.text = "<p>Частота: %8.1f +- %.1f Hz,</p> <p>Энергия: %7.3f +- %.1f МэВ</p>" % ( freq, freq_error, energy, energy_error) fit_handler["fit_line"] = asym_fig.line( fit_line_real_x_axis, fit.get_line(name, fit_line_x_axis, [x['value'] for x in params_]), color="red", line_width=2) fit_button.on_click(fit_callback) # Инициализация bokeh app, расположение виджетов column_1 = column(gridplot([tab_handler], [asym_fig], merge_tools=False), period_input, width=width_ + 50) widgets_ = WidgetBox(depol_start_stop_buttons, depol_input_harmonic_number, depol_input_attenuation, depol_input_speed, depol_input_step, depol_input_initial, depol_input_final, depol_status_window) row_21 = column(hist_fig, hist_slider) column_21 = column(widgets_) if config.GEM_idle: column_22 = column(fit_button, clear_fit_button, fake_depol_button, fit_line_selection_widget, fit_function_selection_widget, energy_window, make_parameters_table()) make_parameters_table_id = 6 else: column_22 = column(fit_button, clear_fit_button, fit_line_selection_widget, fit_function_selection_widget, energy_window, make_parameters_table()) make_parameters_table_id = 5 def rebuild_table(attr, old, new): column_22.children[make_parameters_table_id] = make_parameters_table() fit_function_selection_widget.on_change("value", rebuild_table) row_22 = row(column_21, column_22) column_2 = column(row_21, row_22, width=width_ + 50) layout_ = layout([[column_1, column_2]]) # Настройка документа Bokeh update_data() doc.add_periodic_callback(hist_update, 1000) # TODO запихнуть в один callback doc.add_periodic_callback(update_data, 1000) # TODO: подобрать периоды doc.add_periodic_callback(update_depol_status, 1000) doc.title = "Laser polarimeter" doc.add_root(layout_)
def make_plot(doc): """ This is called every time someone visits a pre-defined endpoint; see the apps dict in the main calling code for what that actualls is. """ # Grab our stashed information from the template plotState = doc.template.globals['plotState'] mods = plotState.modules qdata = plotState.data dset = plotState.colors theme = plotState.theme # # NOTE: Should clean this up or stuff it all into dataGatherer # # Hard coding the access/dict key for the data needed for this plot # Cringe-worthy but tolerable. This MUST match what is set in the # 'modules.conf' file otherwise it'll blow up. moduleKey = 'weather_TempHumi' m = mods[moduleKey] print("Serving %s" % (m.title)) # Use this to consistently filter/gather the data based on some # specific tags/reorganizing r = dataGatherer(m, qdata) # A dict of helpful plot labels ldict = { 'title': "DCT Weather Information", 'xlabel': "Time (UTC)", 'y1label': "Temperature (C)", 'y2label': "Humidity (%)" } # Since we haven't plotted anything yet, we don't have a decent idea # of the bounds that we make our patches over. So just do that manually. # Remember that .min and .max are methods! Need the () # Also adjust plot extents to pad +/- N percent npad = 0.1 y1lim = None y2lim = [0, 100] if y1lim is None: y1lim = [r.DewPoint.min(skipna=True), r.AirTemp.max(skipna=True)] # Now pad them appropriately, checking for a negative limit if y1lim[0] < 0: y1lim[0] *= (1. + npad) else: y1lim[0] *= (1. - npad) if y1lim[1] < 0: y1lim[1] *= (1. - npad) else: y1lim[1] *= (1. + npad) if y2lim is None: # Remember that .min and .max are methods! Need the () y2lim = [r.Humidity.min(skipna=True), r.Humidity.max(skipna=True)] y2lim = [y2lim[0] * (1. - npad), y2lim[1] * (1. + npad)] y2 = {"y2": DataRange1d(start=y2lim[0], end=y2lim[1])} # This does everything else. Loops over the columns in the 'r' DataFrame # and creates a ColumnDataSource for the resulting figure fig, cds, cols = bplot.commonPlot(r, ldict, y1lim, dset, height=400, width=500, y2=y2) sunrise, sunset = bplot.createSunAnnotations(qdata) fig.add_layout(sunrise) fig.add_layout(sunset) # At this point, we're done! Just apply the theme and attach the figure # to the rest of the document, then setup the update callback doc.theme = theme doc.title = m.title doc.add_root(fig) def grabNew(): print("Checking for new data!") # Check our stash qdata = doc.template.globals['plotState'].data timeUpdate = doc.template.globals['plotState'].timestamp tdiff = (dt.datetime.utcnow() - timeUpdate).total_seconds() print("Data were updated %f seconds ago (%s)" % (tdiff, timeUpdate)) # Get the last timestamp present in the existing ColumnDataSource lastTime = cds.data['index'].max() # Turn it into a datetime.datetime (with UTC timezone) lastTimedt = bplot.convertTimestamp(lastTime, tz='UTC') # Sweep up all the data, and filter down to only those # after the given time nf = dataGatherer(m, qdata, timeFilter=lastTimedt) # Check the data for updates, and downselect to just the newest mds2 = bplot.newDataCallback(cds, cols, nf, lastTimedt, y1lim) # Actually update the data if mds2 != {}: cds.stream(mds2, rollover=15000) print("New data streamed; %d row(s) added" % (nf.shape[0])) # Check to see if we have to update the sunrise/sunset times # Create ones so it's super easy to just compare by .location nsunrise, nsunset = bplot.createSunAnnotations(qdata) # Check to see if there's actually an update if sunrise.location != nsunrise.location: print("Updated sunrise span location") sunrise.location = sunrise.location if sunset.location != nsunset.location: print("Updated sunset span location") sunset.location = nsunset.location print() print("") doc.add_periodic_callback(grabNew, 5000) return doc
def test_autorange_prevents_panning_but_can_zoom_in_with_range1d(output_file_url, selenium): plot = make_pan_plot_with_callback(xr=Range1d(0.45, 3, bounds='auto'), yr=DataRange1d(0, 3, bounds='auto')) save(plot) _assert_autorange_prevents_panning_but_can_zoom(output_file_url, selenium)
# coding: utf-8 # In[8]: from bokeh.io import output_file, show from bokeh.models import GMapPlot, GMapOptions, ColumnDataSource, Circle, DataRange1d, PanTool, WheelZoomTool, BoxSelectTool map_options = GMapOptions(lat=30.29, lng=-97.73, map_type="roadmap", zoom=10) plot = GMapPlot( x_range=DataRange1d(), y_range=DataRange1d(), map_options=map_options, title="Austin") plot.api_key = "AIzaSyDea2ehkc_IE8vnhkw-C0AKBLeMu2LCBEo" source = ColumnDataSource( data=dict( lat=[30.29, 30.20, 30.29], lon=[-97.70, -97.74, -97.78], ) ) circle = Circle(x="lon", y="lat", size=15, fill_color="blue", fill_alpha=0.8, line_color=None) plot.add_glyph(source, circle) plot.add_tools(PanTool(), WheelZoomTool(), BoxSelectTool()) output_file("fires.html") show(plot) # In[ ]:
from bokeh.resources import INLINE from bokeh.sampledata.iris import flowers from bokeh.util.browser import view from bokeh.plotting import output_file, show colormap = {'setosa': 'red', 'versicolor': 'green', 'virginica': 'blue'} flowers['color'] = flowers['species'].map(lambda x: colormap[x]) source = ColumnDataSource(data=dict(petal_length=flowers['petal_length'], petal_width=flowers['petal_width'], sepal_length=flowers['sepal_length'], sepal_width=flowers['sepal_width'], color=flowers['color'])) xdr = DataRange1d(bounds=None) ydr = DataRange1d(bounds=None) def make_plot(xname, yname, xax=False, yax=False): mbl = 40 if yax else 0 mbb = 40 if xax else 0 plot = Plot(x_range=xdr, y_range=ydr, background_fill_color="#efe8e2", border_fill_color='white', plot_width=200 + mbl, plot_height=200 + mbb, min_border_left=2 + mbl, min_border_right=2, min_border_top=2,
def __init__(self, **kwargs): self.source = ColumnDataSource(data={'time': [], 'cpu': [], 'memory_percent':[], 'network-send':[], 'network-recv':[]} ) x_range = DataRange1d(follow='end', follow_interval=30000, range_padding=0) resource_plot = Plot( x_range=x_range, y_range=Range1d(start=0, end=1), toolbar_location=None, min_border_bottom=10, **kwargs ) line_opts = dict(line_width=2, line_alpha=0.8) g1 = resource_plot.add_glyph( self.source, Line(x='time', y='memory_percent', line_color="#33a02c", **line_opts) ) g2 = resource_plot.add_glyph( self.source, Line(x='time', y='cpu', line_color="#1f78b4", **line_opts) ) resource_plot.add_layout( LinearAxis(formatter=NumeralTickFormatter(format="0 %")), 'left' ) legend_opts = dict( location='top_left', orientation='horizontal', padding=5, margin=5, label_height=5) resource_plot.add_layout( Legend(items=[('Memory', [g1]), ('CPU', [g2])], **legend_opts) ) network_plot = Plot( x_range=x_range, y_range=DataRange1d(start=0), toolbar_location=None, **kwargs ) g1 = network_plot.add_glyph( self.source, Line(x='time', y='network-send', line_color="#a6cee3", **line_opts) ) g2 =network_plot.add_glyph( self.source, Line(x='time', y='network-recv', line_color="#b2df8a", **line_opts) ) network_plot.add_layout(DatetimeAxis(axis_label="Time"), "below") network_plot.add_layout(LinearAxis(axis_label="MB/s"), 'left') network_plot.add_layout( Legend(items=[('Network Send', [g1]), ('Network Recv', [g2])], **legend_opts) ) tools = [ PanTool(dimensions='width'), WheelZoomTool(dimensions='width'), BoxZoomTool(), ResetTool() ] if 'sizing_mode' in kwargs: sizing_mode = {'sizing_mode': kwargs['sizing_mode']} else: sizing_mode = {} combo_toolbar = ToolbarBox( tools=tools, logo=None, toolbar_location='right', **sizing_mode ) self.root = row( column(resource_plot, network_plot, **sizing_mode), column(combo_toolbar, **sizing_mode), id='bk-resource-profiles-plot', **sizing_mode ) # Required for update callback self.resource_index = [0]
source=source, color=None, selection_color="red") # set both x ranges to the same time range. ts2.x_range = ts1.x_range # third and fourth time series charts: vertical bar charts, split, mean return and std dev and sharpe of returns ts3 = figure(plot_width=500, plot_height=400, tools=tools, x_axis_type='datetime', active_drag="xbox_select") ts3.extra_y_ranges = { "foo_stk": DataRange1d(source.to_df()['CumStockFwdRets'].min(), source.to_df()['CumStockFwdRets'].max()) } ts3.add_layout(LinearAxis(y_range_name="foo_stk"), 'right') # 3rd time series plot ts3.vbar(x="date", top='StockFwdRets', color='blue', alpha=0.5, source=source, legend_label='StockFwdRets', y_range_name="foo_stk") ts3.line('date', 'CumStockFwdRets', source=source, y_range_name='foo_stk') # 4th time series plot ts4 = figure(plot_width=500, plot_height=400,
def __init__(self, n_rectangles=1000, clear_interval=20000, **kwargs): """ kwargs are applied to the bokeh.models.plots.Plot constructor """ self.n_rectangles = n_rectangles self.clear_interval = clear_interval self.last = 0 self.source = ColumnDataSource(data=dict( start=[], duration=[], key=[], name=[], color=[], worker=[], y=[], worker_thread=[], alpha=[]) ) x_range = DataRange1d() y_range = DataRange1d(range_padding=0) self.root = Plot( title=Title(text="Task Stream"), id='bk-task-stream-plot', x_range=x_range, y_range=y_range, toolbar_location="above", min_border_right=35, **kwargs ) self.root.add_glyph( self.source, Rect(x="start", y="y", width="duration", height=0.4, fill_color="color", line_color="color", line_alpha=0.6, fill_alpha="alpha", line_width=3) ) self.root.add_layout(DatetimeAxis(axis_label="Time"), "below") ticker = BasicTicker(num_minor_ticks=0) self.root.add_layout(LinearAxis(axis_label="Worker Core", ticker=ticker), "left") self.root.add_layout(Grid(dimension=1, grid_line_alpha=0.4, ticker=ticker)) self.root.yaxis.major_label_text_alpha = 0 hover = HoverTool( point_policy="follow_mouse", tooltips=""" <div> <span style="font-size: 12px; font-weight: bold;">@name:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@duration</span> <span style="font-size: 10px;">ms</span> </div> """ ) # export = ExportTool() # export.register_plot(self.root) self.root.add_tools( hover, # export, BoxZoomTool(), ResetTool(reset_size=False), PanTool(dimensions="width"), WheelZoomTool(dimensions="width") ) # Required for update callback self.task_stream_index = [0]
df['new_diff'] = new_diffs print(df) sum = round(df['diff'].sum(),0) new_sum = round(df['new_diff'].sum(),0) if df['new_diff'].max() > df['diff'].max(): limit = df['new_diff'].max() else: limit = df['diff'].max() source = ColumnDataSource(df) TOOLS = "pan,wheel_zoom,reset,hover,save" TOOLTIPS = [("BID", "@bid"),("Diff", "@diff"), ('New diff', '@new_diff'), ('Number of segments','@number_of_segments'), ('Number of passengers','@pax_number'),('Book fee', '@book_fee')] p = figure(x_range=FactorRange(factors=bid_list, bounds='auto'), y_range = DataRange1d(bounds =(-limit,limit)), plot_height=1000, width=1500, title="real/exp sum = {0} after fee recalculation = {1}".format(sum, new_sum), toolbar_location=None, tools=TOOLS, tooltips=TOOLTIPS) p.xaxis.major_label_orientation = "vertical" p.vbar(x='bid', top='diff', width=0.9, alpha= 0.2, color='blue',source=source) p.vbar(x='bid', top='new_diff', width=0.9, alpha= 0.3, color='red',source=source) p.xgrid.grid_line_color = None p.y_range.start = -limit p.hover.point_policy = "follow_mouse" show(p)
def __init__(self, scheduler, **kwargs): self.scheduler = scheduler ps = [p for p in scheduler.plugins if isinstance(p, AllProgress)] if ps: self.plugin = ps[0] else: self.plugin = AllProgress(scheduler) data = progress_quads( dict(all={}, memory={}, erred={}, released={}, processing={})) self.source = ColumnDataSource(data=data) x_range = DataRange1d(range_padding=0) y_range = Range1d(-8, 0) self.root = figure(id='bk-task-progress-plot', title='Progress', x_range=x_range, y_range=y_range, toolbar_location=None, **kwargs) self.root.line( # just to define early ranges x=[0, 0.9], y=[-1, 0], line_color="#FFFFFF", alpha=0.0) self.root.quad( source=self.source, top='top', bottom='bottom', left='left', right='right', fill_color="#aaaaaa", line_color='#aaaaaa', fill_alpha=0.1, line_alpha=0.3, ) self.root.quad(source=self.source, top='top', bottom='bottom', left='left', right='released-loc', fill_color="color", line_color="color", fill_alpha=0.6) self.root.quad(source=self.source, top='top', bottom='bottom', left='released-loc', right='memory-loc', fill_color="color", line_color="color", fill_alpha=1.0) self.root.quad( source=self.source, top='top', bottom='bottom', left='memory-loc', right='erred-loc', fill_color='black', fill_alpha=0.5, line_alpha=0, ) self.root.quad( source=self.source, top='top', bottom='bottom', left='erred-loc', right='processing-loc', fill_color='gray', fill_alpha=0.35, line_alpha=0, ) self.root.text(source=self.source, text='show-name', y='bottom', x='left', x_offset=5, text_font_size=value('10pt')) self.root.text(source=self.source, text='done', y='bottom', x='right', x_offset=-5, text_align='right', text_font_size=value('10pt')) self.root.ygrid.visible = False self.root.yaxis.minor_tick_line_alpha = 0 self.root.yaxis.visible = False self.root.xgrid.visible = False self.root.xaxis.minor_tick_line_alpha = 0 self.root.xaxis.visible = False hover = HoverTool(point_policy="follow_mouse", tooltips=""" <div> <span style="font-size: 14px; font-weight: bold;">Name:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@name</span> </div> <div> <span style="font-size: 14px; font-weight: bold;">All:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@all</span> </div> <div> <span style="font-size: 14px; font-weight: bold;">Memory:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@memory</span> </div> <div> <span style="font-size: 14px; font-weight: bold;">Erred:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@erred</span> </div> <div> <span style="font-size: 14px; font-weight: bold;">Ready:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@processing</span> </div> """) self.root.add_tools(hover)
def test_datarange1d_init_with_no_arguments(): datarange1d = DataRange1d() assert datarange1d.start is None assert datarange1d.end is None assert datarange1d.bounds is None
from bokeh.sampledata.iris import flowers colormap = {'setosa': 'red', 'versicolor': 'green', 'virginica': 'blue'} flowers['color'] = flowers['species'].map(lambda x: colormap[x]) source = ColumnDataSource(data=dict(petal_length=flowers['petal_length'], petal_width=flowers['petal_width'], sepal_length=flowers['sepal_length'], sepal_width=flowers['sepal_width'], color=flowers['color'])) text_source = ColumnDataSource(data=dict(xcenter=[125], ycenter=[135])) xdr = DataRange1d(sources=[ source.columns("petal_length", "petal_width", "sepal_length", "sepal_width") ]) ydr = DataRange1d(sources=[ source.columns("petal_length", "petal_width", "sepal_length", "sepal_width") ]) def make_plot(xname, yname, xax=False, yax=False, text=None): plot = Plot(x_range=xdr, y_range=ydr, background_fill="#efe8e2", border_fill='white', title="", min_border=2, h_symmetry=False,
def test_datarange1d_init_with_follow_sets_bounds_to_none(): datarange1d = DataRange1d(follow="start") assert datarange1d.follow == "start" assert datarange1d.bounds is None
def test_numeric_range_log_axis() -> None: s = bpp.get_scale(DataRange1d(), "log") assert isinstance(s, LogScale)
def plot_autocorr( axes, plotters, max_lag, figsize, rows, cols, combined, textsize, labeller, backend_config, backend_kwargs, show, ): """Bokeh autocorrelation plot.""" if backend_config is None: backend_config = {} len_y = plotters[0][-1].size backend_config.setdefault("bounds_x_range", (0, len_y)) backend_config = { **backend_kwarg_defaults(("bounds_y_range", "plot.bokeh.bounds_y_range"), ), **backend_config, } if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults(("dpi", "plot.bokeh.figure.dpi"), ), **backend_kwargs, } figsize, _, _, _, line_width, _ = _scale_fig_size(figsize, textsize, rows, cols) if axes is None: axes = create_axes_grid( len(plotters), rows, cols, figsize=figsize, sharex=True, sharey=True, backend_kwargs=backend_kwargs, ) else: axes = np.atleast_2d(axes) data_range_x = DataRange1d(start=0, end=max_lag, bounds=backend_config["bounds_x_range"], min_interval=5) data_range_y = DataRange1d(start=-1, end=1, bounds=backend_config["bounds_y_range"], min_interval=0.1) for (var_name, selection, isel, x), ax in zip(plotters, (item for item in axes.flatten() if item is not None)): x_prime = x if combined: x_prime = x.flatten() c_i = 1.96 / x_prime.size**0.5 y = autocorr(x_prime) ax.add_layout(BoxAnnotation(bottom=-c_i, top=c_i, fill_color="gray")) ax.segment( x0=np.arange(len(y)), y0=0, x1=np.arange(len(y)), y1=y, line_width=line_width, line_color="black", ) title = Title() title.text = labeller.make_label_vert(var_name, selection, isel) ax.title = title ax.x_range = data_range_x ax.y_range = data_range_y show_layout(axes, show) return axes
def distribution_plot(sdat): p = figure(plot_width=left_col_width + border_width, plot_height=300, x_axis_type='datetime', output_backend="webgl") #, tools=tools) p.min_border_left = border_width p.min_border_top = 0 legend_wording = [] max_pdf = 0 for i, gate in enumerate(gateways): colour = pdfcolours[gate] sdat_g = sdat[sdat.gateway == gate] if sdat_g.shape[0] == 0: continue sdat_g['0'] = 0 sdat_week = sdat_g.set_index('dates')[[ 'days', 'cycle_plan_date', 'planned_actual_date', 'expected_date', 'pdf_curve' ]].resample('W').sum() shape_adjustment = 0.01 sdat_week['cycle_plan_date'] = sdat_week['cycle_plan_date'].replace( 0, np.nan) sdat_week['cycle_plan_date'] = sdat_week[ 'cycle_plan_date'] - 1 - shape_adjustment * (1) sdat_week['planned_actual_date'] = sdat_week[ 'planned_actual_date'].replace(0, np.nan) sdat_week['planned_actual_date'] = sdat_week[ 'planned_actual_date'] - 1 - shape_adjustment * (2) sdat_week['expected_date'] = sdat_week['expected_date'].replace( 0, np.nan) sdat_week['expected_date'] = sdat_week[ 'expected_date'] - 1 - shape_adjustment * (3) sdat_week['gateway'] = gate sdat_week = sdat_week.reset_index() sdat_week['dates_str'] = sdat_week.dates.dt.strftime('%d %b %Y') sdat_week['survival_curve'] = 1 - sdat_week.pdf_curve.cumsum() max_pdf = max(max_pdf, sdat_week.pdf_curve.max()) if ~sdat_g.isPrediction.unique()[0]: sdat_week['pdf_curve'] = np.nan sdat_week['survival_curve'] = 0 sdat_week_vbar = sdat_week[[ 'dates', 'pdf_curve', 'gateway', 'dates_str', 'survival_curve' ]] source = ColumnDataSource(sdat_week_vbar) p.vbar(x='dates', top='pdf_curve', width=0.5, source=source, color=colour, alpha=1) liner = p.line(x='dates', y='pdf_curve', source=source, color=colour, alpha=1) source = ColumnDataSource(sdat_week) circler = p.circle(x='dates', y='planned_actual_date', size=8, source=source, color=colour, alpha=2) diamondr = p.diamond(x='dates', y='cycle_plan_date', size=10, source=source, color=colour, alpha=2) squarer = p.square(x='dates', y='expected_date', size=8, source=source, color=colour, alpha=2) # legend_wording.append((gate,[liner])) legend_wording.append((gate, [liner, circler, diamondr, squarer])) cutoffdate = BoxAnnotation(right=pd.to_datetime(date_asof, format='%Y-%m-%d'), fill_alpha=0.1, fill_color='grey') cutoffdate_x = pd.to_datetime(date_asof, format='%Y-%m-%d') - pd.to_timedelta(4, 'M') cutoffdate_text = Label(x=cutoffdate_x, y=max_pdf * 1.1, text='History', render_mode='css', text_alpha=0.8, text_font_size='9pt') p.yaxis.axis_label = 'Probabilities' p.xaxis.major_label_orientation = np.pi / 4 p.add_tools(HoverTool(tooltips=tooltips, mode='mouse')) p.y_range = Range1d(-0.04, max_pdf * 1.4) p.x_range = DataRange1d( min(cutoffdate_x - pd.to_timedelta(3, 'M'), sdat.dates.min()), sdat.dates.max()) x_legend = sdat_week.dates.max() - pd.to_timedelta(10, 'M') vlinecycleplan = Span(location=-0.01, dimension='width', line_color='grey', line_width=0.5, line_alpha=0.5, line_dash='dashed') vlineplanneddates = Span(location=-0.02, dimension='width', line_color='grey', line_width=0.5, line_alpha=0.5, line_dash='dashed') vlineDAexpected = Span(location=-0.03, dimension='width', line_color='grey', line_width=0.5, line_alpha=0.5, line_dash='dashed') cycleplanlegend = Label(x=x_legend, y=-0.01, text='Cycle Plan', text_font_size="7pt", border_line_alpha=0, background_fill_alpha=0) planneddateslegend = Label(x=x_legend, y=-0.02, text='Planned Timing', text_font_size="7pt", border_line_alpha=0, background_fill_alpha=0) DAexpectedlegend = Label(x=x_legend, y=-0.03, text='DA Expected Date', text_font_size="7pt", border_line_alpha=0, background_fill_alpha=0) legend2 = Legend(items=legend_wording, orientation="vertical") p.add_layout(vlinecycleplan) p.add_layout(vlineplanneddates) p.add_layout(vlineDAexpected) p.add_layout(cutoffdate) p.add_layout(cutoffdate_text) p.add_layout(legend2, "right") p.add_layout(cycleplanlegend) p.add_layout(planneddateslegend) p.add_layout(DAexpectedlegend) p.toolbar.logo = None p.toolbar_location = None title_text = Div( text= '<center><b>Likelihood of completion dates of remaining gateways</b></center>', width=left_col_width + border_width) padding_text = Div(text=f'<br><br><br><br><br><br><br>', style={'font-size': '90%'}, width=left_col_width + border_width, height=50) p1 = column(title_text, padding_text, p) return (p1)
line_width=1, ) # # Add taptool to select from which state to show all the counties # with open(javascript_path + 'callback_map.js', 'r') as f: # callback_world_map = f.read() # callbacktap = CustomJS(args={'ext_datafiles': ext_datafiles, # 'p_graph_glyphs': p_graph_glyphs, # 'p_graph': p_graph, # }, # code=callback_world_map) # taptool = p_map.select(type=TapTool) # taptool.callback = callbacktap # Explicitly initialize x range p_map.x_range = DataRange1d() # Reset on doubltap p_map.js_on_event( 'doubletap', CustomJS(args={ 'p': p_map, }, code=""" p.reset.emit() """)) """ # Map widgets ------------------------------------------------------------------------------------------------ """ # Get the callback script used for many of the widgets with open(javascript_path + 'callback_map_widgets.js', 'r') as f:
from bokeh.client import push_session from bokeh.document import Document from bokeh.models import (ColumnDataSource, DataRange1d, Plot, Circle, WidgetBox, Row, Button, TapTool) document = Document() session = push_session(document) N = 9 x = np.linspace(-2, 2, N) y = x**2 source1 = ColumnDataSource(dict(x=x, y=y, size=[20] * N)) xdr1 = DataRange1d() ydr1 = DataRange1d() plot1 = Plot(x_range=xdr1, y_range=ydr1, plot_width=400, plot_height=400) plot1.title.text = "Plot1" plot1.tools.append(TapTool(plot=plot1)) plot1.add_glyph(source1, Circle(x="x", y="y", size="size", fill_color="red")) source2 = ColumnDataSource(dict(x=x, y=y, color=["blue"] * N)) xdr2 = DataRange1d() ydr2 = DataRange1d() plot2 = Plot(x_range=xdr2, y_range=ydr2, plot_width=400, plot_height=400) plot2.title.text = "Plot2" plot2.tools.append(TapTool(plot=plot2)) plot2.add_glyph(source2, Circle(x="x", y="y", size=20, fill_color="color"))
def __init__(self, **kwargs): data = progress_quads(dict(all={}, memory={}, erred={}, released={})) self.source = ColumnDataSource(data=data) x_range = DataRange1d() y_range = Range1d(-8, 0) self.root = Plot( id='bk-task-progress-plot', x_range=x_range, y_range=y_range, toolbar_location=None, **kwargs ) self.root.add_glyph( self.source, Quad(top='top', bottom='bottom', left='left', right='right', fill_color="#aaaaaa", line_color="#aaaaaa", fill_alpha=0.2) ) self.root.add_glyph( self.source, Quad(top='top', bottom='bottom', left='left', right='released-loc', fill_color="color", line_color="color", fill_alpha=0.6) ) self.root.add_glyph( self.source, Quad(top='top', bottom='bottom', left='released-loc', right='memory-loc', fill_color="color", line_color="color", fill_alpha=1.0) ) self.root.add_glyph( self.source, Quad(top='top', bottom='bottom', left='erred-loc', right='erred-loc', fill_color='#000000', line_color='#000000', fill_alpha=0.3) ) self.root.add_glyph( self.source, Text(text='show-name', y='bottom', x='left', x_offset=5, text_font_size=value('10pt')) ) self.root.add_glyph( self.source, Text(text='done', y='bottom', x='right', x_offset=-5, text_align='right', text_font_size=value('10pt')) ) hover = HoverTool( point_policy="follow_mouse", tooltips=""" <div> <span style="font-size: 14px; font-weight: bold;">Name:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@name</span> </div> <div> <span style="font-size: 14px; font-weight: bold;">All:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@all</span> </div> <div> <span style="font-size: 14px; font-weight: bold;">Memory:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@memory</span> </div> <div> <span style="font-size: 14px; font-weight: bold;">Erred:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@erred</span> </div> """ ) self.root.add_tools(hover)
DataRange1d, PanTool, WheelZoomTool, BoxSelectTool, HoverTool) API_KEY = "AIzaSyBZha7DKqyZDkEBIdsMh1ESZzxXnkZLcYw" df = open('global_terrorism.csv', 'r') df = pd.read_csv(df, sep=',', encoding='latin1', low_memory=False) df['nkill'] = df['nkill'].fillna(0) df = df.loc[df['provstate'] == 'California'] map_options = GMapOptions(lat=36.7783, lng=-119.4179, map_type="roadmap", zoom=6) plot = GMapPlot(x_range=DataRange1d(), y_range=DataRange1d(), map_options=map_options, api_key=API_KEY) plot.title.text = "California Terror Attack Location" source = ColumnDataSource(data=df) circle = Circle(y="latitude", x="longitude", size=10, fill_color="red", fill_alpha=0.8, line_color=None) #print(circle) plot.add_glyph(source, circle)
def test_init_with_float(self): datarange1d = DataRange1d(start=-1.0, end=3.0) assert datarange1d.start == -1.0 assert datarange1d.end == 3.0 assert datarange1d.bounds is None