Exemplo n.º 1
0
def create_panel(dynamic, static, title, size=60):
    """
    return a Panel object with title
    """

    # create a column layout of widgets for setting the dynamic parameters
    dlist = []
    for d in dynamic:

        value = r0[title][d]
        slider = widgetbox(Slider(title=d, value=value, start=0, end=10 * value), width=400, height=size)
        slider.children[0].on_change('value', update_figs)

        text = widgetbox(PreText(text='range:'), width=60, height=size)
        minus = widgetbox(Button(label='-'), width=size, height=size)
        plus = widgetbox(Button(label='+'), width=size, height=size)
        minus.children[0].on_click(update_sliders)
        plus.children[0].on_click(update_sliders)

        dlist.append(column(slider, row(minus, text, plus)))
    dcol = column(dlist)

    # create a column layout of TextInput widgets for setting the static parameters
    slist = []
    for s in static:

        value = str(r0[title][s])
        text = widgetbox(TextInput(value=value, title=s), height=size)
        text.children[0].on_change('value', update_figs)

        slist.append(text)
    scol = column(slist)

    return Panel(child=row(dcol, scol), title=title)
Exemplo n.º 2
0
def test_gridplot_merge_tools_nested():
    p1, p2, p3, p4, p5, p6, p7 = figure(), figure(), figure(), figure(), figure(), figure(), figure()
    r1 = row(p1, p2)
    r2 = row(p3, p4)
    c = column(row(p5), row(p6))

    gridplot([[r1, r2], [c, p7]], merge_tools=True)

    for p in p1, p2, p3, p4, p5, p6, p7:
        assert p.toolbar_location is None
Exemplo n.º 3
0
 def __init__(self, xs, ys):
     self.xs=xs
     self.ys=ys
     self.source = ColumnDataSource(data=dict(xs=xs, ys=ys))
     self.fig = figure(title='sin function',
                       x_range=[min(xs), max(ys)],
                       y_range=[min(ys), max(ys)])
     self.fig.line('xs', 'ys', source=self.source)
     self.text = TextInput(title='Title',
                           value='sin function')
     self.offset = Slider(title="offset", value=0.0,
                          start=-5.0, end=5.0, step=0.1)
     self.amplitude = Slider(title="amplitude", value=1.0,
                             start=-5.0, end=5.0, step=0.1)
     self.phase = Slider(title="phase", value=0.0,
                         start=0.0, end=2*np.pi, step=0.1)
     self.freq = Slider(title="frequency", value=1.0,
                        start=0.1, end=5.1, step=0.1)
     
     widget_list = [self.text, self.offset,
                    self.amplitude, self.phase, self.freq]
     for widget in widget_list:
         if widget!=self.text:
             widget.on_change('value', self.update_data)
         else:
             widget.on_change('value', self.update_title)
     inputs=widgetbox(*[widget_list])
     self.plot=row(inputs,self.fig,width=800)
Exemplo n.º 4
0
def test_layout_html_on_parent_first():
    p = Plot(x_range=Range1d(), y_range=Range1d())

    layout = row(p)
    bie.get_layout_html(layout)

    bie.get_layout_html(p, height=100, width=100)
Exemplo n.º 5
0
    def interactive_figure(self):
        """Add interactivity, ie. the option to show/hide lines to the figure."""

        lines = self.plot_figure()  # Generates a list of lines
        labels = [line for line in lines.keys()]  # Prepare a list of labels for the tickboxes
        lineNames = ['l'+str(x) for x in range(len(lines))]  # Prepare a list of names for the lines
        lines = {k: v for k, v in zip(lineNames, lines.values())}  # Create a dictionary {name: line}
        activeL = list(range(len(lines)))  # List of all line index to mark them as active in CheckboxGroup

        JScode = [self._visible_line_JS(k) for k in lines]  # Generate JavaScript for each line
        JScode = '\n'.join(JScode)  # From a list to a single string

        with open(osjoin(getcwd(), 'mLearning', 'JScodeAllLines.js'), 'r') as fileJS:
            buttonJS = fileJS.read()  # Read JavaScript code from a file to toggle the visibility of all lines
        # with open(osjoin(getcwd(), 'mLearning', 'JScode.js'), 'w+') as codeFile:
        #     codeFile.write(JScode)  # Write whole CustomJS to a file for debugging purposes

        callback = CustomJS(code=JScode, args={})  # Args will be added once checkbox and button are added to lines
        checkbox = CheckboxGroup(labels=labels,
                                 active=activeL,  # Labels to be ticked from the beginning
                                 callback=callback,
                                 name='checkbox')  # JavaScript var name

        buttonCallback = CustomJS(code=buttonJS, args={})  # Same as for callback
        button = Button(label="Select/Unselect All",  # Button HTML text
                        button_type="default",
                        callback=buttonCallback,
                        name='button')  # JavaScript var name

        lines['checkbox'], lines['button'] = checkbox, button  # Adding widget to lines
        callback.args, buttonCallback.args = lines, lines  # And then lines to callback
        layout = row(self.fig, widgetbox(children=[button, checkbox], width=200))  # One row, two columns

        logging.debug('Interaction implemented')
        return layout
Exemplo n.º 6
0
    def __init__(self, target):
        self.target = target[::-1]
        self.source1 = ColumnDataSource(data=dict(image=[self.target]))
        self.alpha = Slider(title="alpha", value=30,
                            start=10, end=50, step=1)
        self.sigma = Slider(title="sigma", value=3,
                            start=1, end=20, step=1)

        self.fig1 = self.define_figure('image')
        self.regist_image(self.fig1,self.source1)

        blurred = ndi.gaussian_filter(self.target, sigma=self.sigma.value)
        self.source2 = ColumnDataSource(data=dict(image=[blurred]))
        self.fig2 = self.define_figure('blurred')
        self.regist_image(self.fig2,self.source2)


        filtered = ndi.gaussian_filter(blurred, sigma=1)
        sharped = blurred+self.alpha.value*(blurred-filtered)
        sharped = sharped.astype(np.uint8)
        self.source3 = ColumnDataSource(data=dict(image=[sharped]))
        self.fig3 = self.define_figure('sharped')
        self.regist_image(self.fig3,self.source3)

        widget_list = [self.alpha, self.sigma]
        for widget in widget_list:
            widget.on_change('value', self.update_data)
        inputs = widgetbox(*[widget_list])
        self.plot = row(inputs, gridplot(
            [[self.fig1, self.fig2, self.fig3]]), width=600)
Exemplo n.º 7
0
 def test_layout(self):
     p = figure(plot_width=200, plot_height=300)
     d = Document()
     d.add_root(row(p))
     with pytest.warns(UserWarning) as warns:
         util.set_single_plot_width_height(d, 400, 500)
         assert len(warns) == 1
         assert warns[0].message.args[0] == _SIZE_WARNING
Exemplo n.º 8
0
    def compose_layout(self):
        """Compose the layout ot the app, the main elements are the widgets to
        select the dataset, the metric, a div for the title, a plot and a table
        """

        # Load metrics and datasets
        self.metrics = get_metrics(default='AM1')
        self.datasets = get_datasets(default='cfht')

        # Get args from the app URL or use defaults
        args = get_url_args(doc=curdoc,
                            defaults={'metric': self.metrics['default']})

        self.selected_dataset = args['ci_dataset']

        self.selected_metric = args['metric']

        # get specifications for the selected metric
        self.specs = get_specs(self.selected_metric)

        self.selected_window = args['window']

        # dataset select widget
        dataset_select = Select(title="Data Set:",
                                value=self.selected_dataset,
                                options=self.datasets['datasets'], width=100)

        dataset_select.on_change("value", self.on_dataset_change)

        # thresholds are used to make plot annotations
        self.configure_thresholds()

        # metric select widget
        metric_select = Select(title="Metric:", value=self.selected_metric,
                               options=self.metrics['metrics'], width=100)

        metric_select.on_change("value", self.on_metric_change)

        self.data = \
            get_meas_by_dataset_and_metric(self.selected_dataset,
                                           self.selected_metric,
                                           self.selected_window)

        self.update_data_source()
        self.make_plot()
        self.make_table()

        if len(self.data['values']) < 1:
            self.loading.text = "No data to display"
        else:
            self.loading.text = ""

        self.layout = column(row(widgetbox(metric_select, width=150),
                                 widgetbox(dataset_select, width=150)),
                             widgetbox(self.title, width=1000),
                             self.plot,
                             widgetbox(self.table_title, width=1000),
                             self.table)
def main():
    """Invoke when run directly as a program."""
    args = parse_arguments()

    df = pd.read_csv(args.infile, sep='\s+', names=["amplicon", "meancov", "gene"])

    df['offsetcov'] = df['meancov'] + 0.1  # shift zero values by 0.1
    df = df.dropna().reset_index(drop=True)

    # Make a hover (show amplicon name on mouse-over)
    hover = HoverTool(tooltips=[("Amplicon", "@names"), ("Y value", "$y")])
    tools = [PanTool(), BoxZoomTool(), WheelZoomTool(), RedoTool(), UndoTool(), ResetTool(), hover, SaveTool()]

    # Produce plot
    output_file(args.outfile)
    fig = figure(tools=tools, width=1200, height=600, y_axis_type='log')

    # Fill plot with one point for each amplicon:
    xvals, yvals, labels, colors = [], [], [], []
    for i, (name, group) in enumerate(df.groupby('gene', sort=False)):
        xvals.extend(list(group.index))
        yvals.extend(list(group.offsetcov))
        labels.extend(list(group.amplicon))
        # Elements in the same group should have the same color. Cycle between colors in COLOR_CYCLE:
        colors.extend([COLOR_CYCLE[i % len(COLOR_CYCLE)]] * len(list(group.index)))
    data = ColumnDataSource(data=dict(x=xvals, y=yvals, names=labels, colors=colors))
    fig.circle(x='x', y='y', color='colors', size=10, source=data)

    # Make span lines on 0.05, 0.1, 0.2, 1 and 5 mutiples of mean amplicon coverage:
    mean_coverage = df.offsetcov.mean()
    span_lines = [(5.0, 'Blue'), (1.0, 'Green'), (0.2, 'Red'), (0.1, 'Purple'), (0.05, 'Magenta')]
    xmin, xmax = min(xvals) - 1, max(xvals) + 1
    for ratio, color in span_lines:
        fig.line([xmin, xmax], [mean_coverage * ratio] * 2, line_color=color, line_dash='dashed',
                 legend='{:.0f} % of mean coverage'.format(ratio * 100))

    # Customize plot:
    ymax = 2.0 * max(df.offsetcov.max() + 1000, mean_coverage * 5)
    ymin = 0.2
    fig.y_range = Range1d(ymin, ymax)
    fig.x_range = Range1d(xmin, xmax)
    fig.xaxis.major_tick_line_color = None  # Turn off x-axis major ticks
    fig.xaxis.minor_tick_line_color = None  # Turn off x-axis minor ticks
    fig.xaxis.major_label_text_font_size = '0pt'  # Hack to remove tick labels
    fig.xaxis.axis_label = 'Amplicon'
    fig.yaxis.axis_label = 'Log10 (Amplicon coverage)'

    fig.legend.location = "bottom_right"

    script, div = components(layouts.row(fig))
    with open(os.path.join(os.path.dirname(args.outfile), 'plot.js'), 'wt') as jfile:
        jfile.write('\n'.join(script.split('\n')[2:-1]))
    with open(args.outfile, 'wt') as ofile:
        env = Environment(loader=FileSystemLoader(os.path.dirname(args.template)))
        page_template = env.get_template(os.path.basename(args.template))
        html_text = page_template.render({'bokeh_div': div})  # pylint: disable=no-member
        ofile.write(html_text)
Exemplo n.º 10
0
def createMap(data, selectorColumn='MetricName'):
    # unique names
    ops = list(data[selectorColumn].unique())

    # data
    msk = data[selectorColumn] == ops[0]
    source = ColumnDataSource(data=dict(lat=data['Latitude'][msk], lon=data['Longitude'][msk],
                                        disp=data['DisplayName'][msk], metric=data['MetricName'][msk],
                                        name=data['OrganisationName'][msk],
                                        value=data['Value'][msk]))

    all = {}
    for o in ops:
        msk = data[selectorColumn] == o
        all[o] = dict(lat=data['Latitude'][msk], lon=data['Longitude'][msk],
                                        disp=data['DisplayName'][msk], metric=data['MetricName'][msk],
                                        name=data['OrganisationName'][msk],
                                        value=data['Value'][msk])
    all = ColumnDataSource(all)

    # create figure
    bk.output_file("MetricsMap.html", mode="cdn")
    fig = GMapPlot(plot_width=800, plot_height=700, logo=None,
                 x_range=Range1d(), y_range=Range1d(),
                 map_options=GMapOptions(lat=53.4808, lng=-1.2426, zoom=7),
                 api_key='AIzaSyBQH3HGn6tpIrGxekGGRAVh-hISYAPsM78')
    fig.map_options.map_type = "roadmap"
    fig.title.text = "Performance Metrics"

    # hovering information
    hover = HoverTool(tooltips=[("Name", "@name"),
                                ("Metrics", "@metric"),
                                ("Value", "@value")])

    # add tools
    fig.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), hover)

    # add data
    circle = Circle(x="lon", y="lat", size=5, fill_color="blue",
                    fill_alpha=0.8, line_color=None)
    fig.add_glyph(source, circle)

    # create callback
    callback = CustomJS(args=dict(source=source), code="""
        var f = cb_obj.get('value');
        var d = all.get('data')[f];

        source.set('data', d);
        source.trigger('change');
        """)
    callback.args["source"] = source
    callback.args["all"] = all
    # Set up widgets
    select = Select(title="Select", value=ops[0], options=ops, callback=callback)

    # show the map
    bk.show(row(select, fig))
Exemplo n.º 11
0
    def __init__(self, worker, **kwargs):
        with log_errors():
            self.worker = worker

            names = ['nbytes', 'duration', 'bandwidth', 'count', 'type',
                     'inout-color', 'type-color', 'key', 'key-color', 'start',
                     'stop']
            quantities = ['nbytes', 'duration', 'bandwidth', 'count',
                          'start', 'stop']
            colors = ['inout-color', 'type-color', 'key-color']

            # self.source = ColumnDataSource({name: [] for name in names})
            self.source = ColumnDataSource({
                'nbytes': [1, 2],
                'duration': [0.01, 0.02],
                'bandwidth': [0.01, 0.02],
                'count': [1, 2],
                'type': ['int', 'str'],
                'inout-color': ['blue', 'red'],
                'type-color': ['blue', 'red'],
                'key': ['add', 'inc'],
                'start': [1, 2],
                'stop': [1, 2]
                })

            self.x = Select(title='X-Axis', value='nbytes', options=quantities)
            self.x.on_change('value', self.update_figure)

            self.y = Select(title='Y-Axis', value='bandwidth', options=quantities)
            self.y.on_change('value', self.update_figure)

            self.size = Select(title='Size', value='None',
                               options=['None'] + quantities)
            self.size.on_change('value', self.update_figure)

            self.color = Select(title='Color', value='inout-color',
                                options=['black'] + colors)
            self.color.on_change('value', self.update_figure)

            if 'sizing_mode' in kwargs:
                kw = {'sizing_mode': kwargs['sizing_mode']}
            else:
                kw = {}

            self.control = widgetbox([self.x, self.y, self.size, self.color],
                                     width=200, **kw)

            self.last_outgoing = 0
            self.last_incoming = 0
            self.kwargs = kwargs

            self.layout = row(self.control, self.create_figure(**self.kwargs),
                              **kw)

            self.root = self.layout
Exemplo n.º 12
0
def create_layout():
    year_select = Select(title="Year:", value="2010", options=years)
    location_select = Select(title="Location:", value="World", options=locations)

    year_select.on_change('value', on_year_change)
    location_select.on_change('value', on_location_change)

    controls = row(children=[year_select, location_select])
    layout = column(children=[controls, pyramid(), population()])

    return layout
Exemplo n.º 13
0
    def createLayout(self):
        # Layout of Page
        self.inputTab1 = Panel(child=self.TW_rocks,  title='Rock Models')
        self.inputTab2 = Panel(child=self.TW_fluids, title='Fluid Mixes')
        self.inputTab3 = Panel(child=self.TW_pres,   title='Pressure Scenarios')
        self.inputTab4 = Panel(child=self.TW_out,    title='Model Calculations')

        self.inputTabs = Tabs(tabs=[self.inputTab1, self.inputTab2,
                                    self.inputTab3, self.inputTab4],
                                    width=self.pagewidth, height=200)

        textrowob = Div(text="<h1> Overburden: </h1>")
        selectrowob = row(self.selectObr, self.selectObf, width=500, height=50, sizing_mode="scale_both")
        textrowres = Div(text="<h1> Reservoir: </h1>")
        selectrowres = row(self.selectResR, self.selectResf, width=500, height=50, sizing_mode="scale_both")
        selectrowpres = row(self.selectPres, self.slideDepth, width=500, height=50, sizing_mode="scale_both")
        self.layout = column(self.inputTabs,
                             textrowob,
                             selectrowob,
                             textrowres,
                             selectrowres,
                             selectrowpres, width=self.pagewidth)
Exemplo n.º 14
0
Arquivo: plot.py Projeto: jni/prin
def serve(datasource):
    columns = list(datasource.keys())
    positive_vars = [k for k in columns if np.all(datasource[k] > 0)]
    x = Select(title='X-Axis', value='in_degree',
               options=columns)
    y = Select(title='Y-Axis', value='pagerank',
               options=columns)
    size = Select(title='Size', value='None',
                  options=['None'] + positive_vars)
    color = Select(title='Color', value='None',
                    options=['None'] + columns)
    controls = layouts.widgetbox([x, y, color, size], width=200)
    plot = bokeh_plot(datasource)
    document = layouts.row(controls, plot)
Exemplo n.º 15
0
 def modify_document(self, doc):
     self.network.whois()
     devices_df = self.network.devices
     dev = ColumnDataSource(devices_df)
     columns = [
         TableColumn(field=" Device ID", title="Dev ID"),
         TableColumn(field="Address", title="Address"),
         TableColumn(field="Manufacturer", title="Manuf"),
         TableColumn(field="Name", title="Name"),
     ]
     data_table = DataTable(source=dev, columns=columns)
     layout = row([data_table])
     doc.add_root(layout)
     doc.title = "BACnet devices"
     return doc
Exemplo n.º 16
0
    def modify_document(self, doc):

        controller = self.network.notes[0]
        notes_df = pd.DataFrame(self.network.notes[1]).reset_index()
        notes_df.columns = ["index", "notes"]
        notes = ColumnDataSource(notes_df)
        self.columns = [
            TableColumn(field="index", title="Timestamp"),
            TableColumn(field="notes", title="Notes"),
        ]
        self.data_table = DataTable(source=notes, columns=self.columns)
        layout = row([self.data_table])
        doc.add_root(layout)
        doc.title = "Notes for %s" % controller
        # doc.add_periodic_callback(self.update_data,100)
        return doc
Exemplo n.º 17
0
def modify_doc(doc):
    x = np.linspace(0, 10, 1000)
    y = np.log(x) * np.sin(x)

    source = ColumnDataSource(data=dict(x=x, y=y))

    plot = figure(title="Simple plot with slider")
    plot.line('x', 'y', source=source)

    slider = Slider(start=1, end=10, value=1, step=0.1)

    def callback(attr, old, new):
        y = np.log(x) * np.sin(x*new)
        source.data = dict(x=x, y=y)
    slider.on_change('value', callback)

    doc.add_root(row(widgetbox(slider), plot))
Exemplo n.º 18
0
    def __init__(self, server, sizing_mode='stretch_both', **kwargs):
        self.server = server
        self.counter_figures = {}
        self.counter_sources = {}
        self.digest_figures = {}
        self.digest_sources = {}
        self.sizing_mode = sizing_mode

        if self.server.digests:
            for name in self.server.digests:
                self.add_digest_figure(name)
        for name in self.server.counters:
            self.add_counter_figure(name)

        figures = merge(self.digest_figures, self.counter_figures)
        figures = [figures[k] for k in sorted(figures)]

        if len(figures) <= 5:
            self.root = column(figures, sizing_mode=sizing_mode)
        else:
            self.root = column(*[row(*pair, sizing_mode=sizing_mode)
                                 for pair in partition_all(2, figures)],
                               sizing_mode=sizing_mode)
Exemplo n.º 19
0
                       title=u"选择因子",
                       width=300,
                       options=factors_list)
factor_select.on_change('value', lambda attr, old, new: update_factor_data())
window_select = Select(value='20', title=u'选择窗口', width=300, options=ks)
window_select.on_change('value', lambda attr, old, new: update_factor_data())
metrics_select = Select(value="Normal_IC",
                        title=u"因子衡量标准",
                        width=300,
                        options=metrics)

recalculate()
update_data()
update_factor_data()

time_input = row(train_date_text, test_date_text)
momentum_factor_input = row(five_day_return_text,
                            hundred_twenty_day_return_text,
                            thirty_day_average_return_text)
value_factor_input = row(pe_text)
defensive_factor_input = row(thirty_day_volatility)
factor_input = row(factor_select, window_select, metrics_select)
inputs = column(time_input, momentum_factors, momentum_factor_input,
                value_factors, value_factor_input, defensive_factors,
                defensive_factor_input, factor_input)

curdoc().add_root(
    column(inputs, update_button, plot_normal_ic, plot_cone, plot_group,
           plot_value, plot_return))
curdoc().title = u"因子模型"
Exemplo n.º 20
0
    global layout
    global energy_per_capita

    new_df = data_changed(energy_per_capita)
    if new_df is not None:
        energy_per_capita = new_df
        plots_box.children[0] = create_line(energy_per_capita)
        plots_box.children[1] = create_bar(energy_per_capita)


line = create_line(energy_per_capita)
bar = create_bar(energy_per_capita)
desc1 = Paragraph(text="""
This example shows live integration between bokeh server and Excel using
XLWings.""")
desc2 = Paragraph(text="""
*** YOU MUST HAVE EXCEL and XLWINGS INSTALLED ON YOUR MACHINE FOR IT TO WORK ***
""")
desc3 = Paragraph(text="""
It opens this plots window and an excel spreadsheet instance with the
values being plotted. When user changes the values on the excel spreadsheet
the plots will be updated accordingly. It's not required to save the spreadsheet for the plots to update.
""")
plots_box = row(line, bar)
layout = column(desc1, desc2, desc3, plots_box)
curdoc().add_root(layout)
curdoc().add_periodic_callback(update, 500)

session.show()  # open the document in a browser
session.loop_until_closed()  # run forever
ss2 = s2.data_source

x_axis = Span(location=0,
              dimension='width',
              line_color='black',
              line_alpha=0.4,
              line_width=2)
p2.add_layout(x_axis)
# endregion

# region Create a third graph to show accuracy of predictions
p3 = figure(plot_width=800, plot_height=800)
# endregion

# region global Variables
c = row(p, p2, p3)
step_count = []
x_point = []
y_point = []
pred_peak = []
peaktpeak = []
# endregion

# region Choose stock ticker
ticker = 'MSFT'
# endregion


@linear()
def update(step):
    # region Get stock price
Exemplo n.º 22
0
source = ColumnDataSource(data={'x': fertility, 'y': female_literacy})

# Create a new plot: plot
plot = figure()

# Add circles to the plot
plot.circle('x', 'y', source=source)


# Define a callback function: update_plot
def update_plot(attr, old, new):
    # If the new Selection is 'female_literacy', update 'y' to female_literacy
    if new == 'female_literacy':
        source.data = {'x': fertility, 'y': female_literacy}
    # Else, update 'y' to population
    else:
        source.data = {'x': fertility, 'y': population}


# Create a dropdown Select widget: select
select = Select(title="distribution",
                options=['female_literacy', 'population'],
                value='female_literacy')

# Attach the update_plot callback to the 'value' property of select
select.on_change('value', update_plot)

# Create layout and add to current document
layout = row(select, plot)
curdoc().add_root(layout)
Exemplo n.º 23
0
  def get_layout_data(self):
    H_LINE_1 = 20
    H_LINE_2 = 40
    H_GRAPH  = 220 
    W_INFO_LABEL = 100
    W_INFO_SIZE = 400
    W_BOX1 = W_INFO_LABEL + W_INFO_SIZE
    H_PLOT = 380
    TOOLS = 'save,hover'
    data_table = DataTable(
      source=self.DS, 
      columns=self.table_columns,
      width=W_INFO_LABEL + W_INFO_SIZE, 
      height=H_LINE_1 + H_LINE_2 + H_GRAPH,
      sizing_mode="stretch_width",
      )
    self.div_status = Div(text='', width=W_INFO_SIZE, height=H_LINE_2, background='lightyellow')
    div_status_label = Div(text='Informatii:', width=W_INFO_LABEL)
    info_row = row(div_status_label, self.div_status)
    
    inputs_and_status = []
    if self.debug:
      FN = self.log.config_data['DATA']
      self.df = self.log.load_dataframe(FN, folder='output')
      self.log.P("Loaded data from '{}':\n{}".format(FN, self.df.iloc[:5,:10]))
      inputs_and_status = [
          row(
            Div(text='Datele incarcate:', width=W_INFO_LABEL),
            Div(text=FN, width=W_INFO_SIZE, height=H_LINE_1, background="lightyellow")
            )            
        ]
    else:
      file_inp = FileInput(accept=".csv", width=W_INFO_SIZE,height=H_LINE_1)
      file_inp.on_change('value', self.upload_data)
      inputs_and_status = [row(
        Div(text='Incarcati fisierul:', width=W_INFO_LABEL),
        file_inp
        )]
      
    bar_list = self.config['BARS']
    all_bar_lines = []
    bars = []    
    width = W_BOX1 #self.W // len(bar_list)
    self.log.P("Plot width: {}".format(width))
    for dct_count_data in self.counts_data:
      bar = dct_count_data['FIELD']
      new_line = dct_count_data.get('NEWLINE', 0)      
      is_progress = dct_count_data.get('PROGRESS', 0)
      if new_line:
        if len(bars) == 0:
          raise ValueError('Cannot change bar line with no graphs before')
        all_bar_lines.append(row(bars))
        bars = []
      if bar in bar_list:
        bar_name = dct_count_data['TITLE']
        data_type = dct_count_data['TYPE'].upper()
        title = 'Analiza {} dupa '.format(
          "evolutiei procesului de screening" if is_progress else "distributiei totale" 
          ) + bar_name
        options = dict(
          title=title,
          sizing_mode='stretch_width',
          tools=TOOLS,
          width=width, 
          height=H_PLOT, 
          )
        if data_type in ["STR", "DATE"]:
          p = figure(
            x_range=['one','two', '...'],
            **options,
            ) 
          p.xaxis.major_label_orientation = np.pi/3
          p_labels = LabelSet(
            x='value', y='count', 
            text='count', level='glyph',
            x_offset=-13.5, y_offset=0, 
            source=dct_count_data['DS'], 
            render_mode='canvas'
            )   
          p.add_layout(p_labels)
        else:
          p = figure(
            **options
            ) 
        plot = p.vbar(x='value', top='count', source=dct_count_data['DS'], width=0.9)
        p.y_range.start = 0
        p.y_range.range_padding = 0.2
        p.xgrid.grid_line_color = None

        dct_count_data['FIGURE'] = p
        dct_count_data['PLOT'] = plot
        
        self.set_figure_range(bar)
        bars.append(p)
  
    all_bar_lines.append(row(bars))
    bars = []

    for dct_count_data in self.counts_data:
      bar = dct_count_data['FIELD']
      is_analysis_by_target = dct_count_data.get('TARGET_ANALYSIS', 0)
      if not is_analysis_by_target:
        continue
      new_line = dct_count_data.get('NEWLINE', 0)      
      is_progress = dct_count_data.get('PROGRESS', 0)
      if new_line:
        if len(bars) == 0:
          raise ValueError('Cannot change bar line with no graphs before')
        all_bar_lines.append(row(bars))
        bars = []
      if bar in bar_list:
        bar_name = dct_count_data['TITLE']
        data_type = dct_count_data['TYPE'].upper()
        title = 'Analiza {} dupa '.format(
          "evolutiei procesului de screening" if is_progress else "distributiei cazurilor {}".format(self.target_positive)
          ) + bar_name
        options = dict(
          title=title,
          sizing_mode='stretch_width',
          tools=TOOLS,
          width=width, 
          height=H_PLOT, 
          )
        if data_type in ["STR", "DATE"]:
          p = figure(
            x_range=['one','two', '...'],
            **options,
            ) 
          p.xaxis.major_label_orientation = np.pi/3
          p_labels = LabelSet(
            x='value', y='count', 
            text='count', level='glyph',
            x_offset=-13.5, y_offset=0, 
            source=dct_count_data['DS_TARGET'], 
            render_mode='canvas'
            )   
          p.add_layout(p_labels)
        else:
          p = figure(
            **options
            ) 
        plot = p.vbar(x='value', top='count', source=dct_count_data['DS_TARGET'], width=0.9)
        p.y_range.start = 0
        p.y_range.range_padding = 0.2
        p.xgrid.grid_line_color = None

        dct_count_data['FIGURE_TARGET'] = p
        dct_count_data['PLOT_TARGET'] = plot
        
        self.set_figure_range(bar)
        bars.append(p)
    
    all_bar_lines.append(row(bars))

        
    p_target = figure(
      title=self.target_data['TITLE'],
      x_range=['one','two', '...'],
      width=W_INFO_SIZE,
      height=H_GRAPH,
      tools=TOOLS
      )
    
    p_target.y_range.start = 0
    p_target.y_range.range_padding = 0.3
    plot_target = p_target.vbar(
      x='value', 
      top='count', 
      source=self.target_data['DS'], 
      width=0.9)

    labels = LabelSet(
      x='value', y='count', 
      text='count', level='glyph',
      x_offset=-13.5, y_offset=0, 
      source=self.target_data['DS'], 
      render_mode='canvas'
      )   
    p_target.add_layout(labels)
    self.target_data['FIGURE'] = p_target
    self.target_data['PLOT'] = plot_target
    target_row = row(
      Div(text='Distributia rezultatelor:',width=100),
      p_target
      )
    self.set_figure_range(self.target_data['FIELD'])
    
    inputs_and_status += [info_row, target_row]
    ctrl_input = column(inputs_and_status)
    bar_plots = column(all_bar_lines)
    data_ctrls = row(ctrl_input, data_table, sizing_mode="stretch_width")
    this_layout = column(data_ctrls, bar_plots, sizing_mode="stretch_width")
    
    # app_layout = layout(
    #   [
    #     [ctrl_input]
    #     [data_table],
    #   ], 
    #   # sizing_mode="scale_both"
    #   )
    
    return this_layout
Exemplo n.º 24
0
              y_range=[-2.5, 2.5])

plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

freq = Slider(title="frequency", value=1.0, start=0.1, end=5.1, step=0.1)


def update_data(attrname, old, new):

    k = freq.value

    # Generate the new curve
    x = np.linspace(0, 4 * np.pi, N)
    y = np.sin(k * x)

    source.data = dict(x=x, y=y)


freq.on_change('value', update_data)

# Set up layouts and add to document
widget_box = widgetbox(freq)

curdoc().add_root(row(widget_box, plot, width=800))
curdoc().title = "Sliders"

# def change_slider_in_python():
#     freq.value = np.random.uniform(0.1, 5.1)
#
# curdoc().add_periodic_callback(change_slider_in_python, 2000)
Exemplo n.º 25
0
def update():
    current = df[(df['salary'] >= slider.value[0]) & (df['salary'] <= slider.value[1])].dropna()
    source.data = {
        'name'             : current.name,
        'salary'           : current.salary,
        'years_experience' : current.years_experience,
    }

slider = RangeSlider(title="Max Salary", start=10000, end=110000, value=(10000, 50000), step=1000, format="0,0")
slider.on_change('value', lambda attr, old, new: update())

button = Button(label="Download", button_type="success")
button.callback = CustomJS(args=dict(source=source),
                           code=open(join(dirname(__file__), "download.js")).read())

columns = [
    TableColumn(field="name", title="Employee Name"),
    TableColumn(field="salary", title="Income", formatter=NumberFormatter(format="$0,0.00")),
    TableColumn(field="years_experience", title="Experience (years)")
]

data_table = DataTable(source=source, columns=columns, width=800)

controls = widgetbox(slider, button)
table = widgetbox(data_table)

curdoc().add_root(row(controls, table))
curdoc().title = "Export CSV"

update()
Exemplo n.º 26
0
        color="white",
        line_color="#3A5785")
vh1 = pv.quad(left=0,
              bottom=vedges[:-1],
              top=vedges[1:],
              right=vzeros,
              alpha=0.5,
              **LINE_ARGS)
vh2 = pv.quad(left=0,
              bottom=vedges[:-1],
              top=vedges[1:],
              right=vzeros,
              alpha=0.1,
              **LINE_ARGS)

layout = column(row(p, pv), row(ph, Spacer(width=200, height=200)))

curdoc().add_root(layout)
curdoc().title = "Selection Histogram"


def update(attr, old, new):
    inds = np.array(new['1d']['indices'])
    if len(inds) == 0 or len(inds) == len(x):
        hhist1, hhist2 = hzeros, hzeros
        vhist1, vhist2 = vzeros, vzeros
    else:
        neg_inds = np.ones_like(x, dtype=np.bool)
        neg_inds[inds] = False
        hhist1, _ = np.histogram(x[inds], bins=hedges)
        vhist1, _ = np.histogram(y[inds], bins=vedges)
Exemplo n.º 27
0
def update_data(attrname, old, new):

    #a = aperture.value
    m = magnitude.value
    e = exptime.value

    luvoir.aperture = aperture.value
    hdi.set_pixel_sizes(luvoir)  # adaptively set the pixel sizes

    wave = hdi.pivotwave
    snr = phot_etc.compute_snr(luvoir, hdi, e, m)
    source.data = dict(x=wave[2:-3], y=snr[2:-3], desc=hdi.bandnames[2:-3])
    source2.data = dict(x=hdi.pivotwave[0:2],
                        y=snr[0:2],
                        desc=hdi.bandnames[0:2])
    source3.data = dict(x=hdi.pivotwave[-3:],
                        y=snr[-3:],
                        desc=hdi.bandnames[-3:])


for w in [aperture, exptime, magnitude]:  # iterate on changes to parameters
    w.on_change('value', update_data)

# Set up layouts and add to document
inputs = WidgetBox(children=[aperture, exptime, magnitude])
curdoc().add_root(row(children=[inputs, snr_plot]))
script = autoload_server(model=None,
                         app_path="/simple_etc",
                         url="pancho.local:5006")
#print(script)
Exemplo n.º 28
0
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_)
Exemplo n.º 29
0
            tools='box_select,pan,wheel_zoom,box_zoom,reset',
            x_range=[
                min(country_cases['confirmed']),
                max(country_cases['confirmed']) + 35000
            ],
            y_range=[
                min(country_cases['recovered']),
                max(country_cases['recovered']) + 2000
            ])

hover = HoverTool(tooltips=[('Country',
                             '@country'), ('Number of Confirmed Cases',
                                           '@x'), ('Number of Recoveries',
                                                   '@y')])

p1.add_tools(hover)

p1.circle(x='x',
          y='y',
          size='sizes',
          source=source,
          color={
              'field': 'y',
              'transform': color_mapper
          })

layout = row(p, p1)

output_file('cor.html')
show(layout)
Exemplo n.º 30
0
def spectroscopy_plot(source_id):
    """TODO normalization? should this be handled at data ingestion or plot-time?"""
    source = Source.query.get(source_id)
    spectra = Source.query.get(source_id).spectra
    if len(spectra) == 0:
        return None, None, None

    color_map = dict(zip([s.id for s in spectra], viridis(len(spectra))))
    data = pd.concat([
        pd.DataFrame({
            'wavelength': s.wavelengths,
            'flux': s.fluxes,
            'id': s.id,
            'instrument': s.instrument.telescope.nickname
        }) for i, s in enumerate(spectra)
    ])
    split = data.groupby('id')
    hover = HoverTool(tooltips=[('wavelength',
                                 '$x'), ('flux',
                                         '$y'), ('instrument', '@instrument')])
    plot = figure(plot_width=600,
                  plot_height=300,
                  sizing_mode='scale_both',
                  tools='box_zoom,wheel_zoom,pan,reset',
                  active_drag='box_zoom')
    plot.add_tools(hover)
    model_dict = {}
    for i, (key, df) in enumerate(split):
        model_dict['s' + str(i)] = plot.line(x='wavelength',
                                             y='flux',
                                             color=color_map[key],
                                             source=ColumnDataSource(df))
    plot.xaxis.axis_label = 'Wavelength (Å)'
    plot.yaxis.axis_label = 'Flux'
    plot.toolbar.logo = None

    # TODO how to choose a good default?
    plot.y_range = Range1d(0, 1.03 * data.flux.max())

    toggle = CheckboxWithLegendGroup(
        labels=[s.instrument.telescope.nickname for s in spectra],
        active=list(range(len(spectra))),
        width=100,
        colors=[color_map[k] for k, df in split])
    toggle.callback = CustomJS(args={
        'toggle': toggle,
        **model_dict
    },
                               code="""
          for (let i = 0; i < toggle.labels.length; i++) {
              eval("s" + i).visible = (toggle.active.includes(i))
          }
    """)

    elements = CheckboxWithLegendGroup(
        labels=list(SPEC_LINES.keys()),
        active=[],
        width=80,
        colors=[c for w, c in SPEC_LINES.values()])
    z = TextInput(value=str(source.red_shift), title="z:")
    v_exp = TextInput(value='0', title="v_exp:")
    for i, (wavelengths, color) in enumerate(SPEC_LINES.values()):
        el_data = pd.DataFrame({'wavelength': wavelengths})
        el_data['x'] = el_data['wavelength'] * (1 + source.red_shift)
        model_dict[f'el{i}'] = plot.segment(
            x0='x',
            x1='x',
            # TODO change limits
            y0=0,
            y1=1e-13,
            color=color,
            source=ColumnDataSource(el_data))
        model_dict[f'el{i}'].visible = False

    # TODO callback policy: don't require submit for text changes?
    elements.callback = CustomJS(args={
        'elements': elements,
        'z': z,
        'v_exp': v_exp,
        **model_dict
    },
                                 code="""
          let c = 299792.458; // speed of light in km / s
          for (let i = 0; i < elements.labels.length; i++) {
              let el = eval("el" + i);
              el.visible = (elements.active.includes(i))
              el.data_source.data.x = el.data_source.data.wavelength.map(
                  x_i => (x_i * (1 + parseFloat(z.value)) /
                                (1 + parseFloat(v_exp.value) / c))
              );
              el.data_source.change.emit();
          }
    """)
    z.callback = elements.callback
    v_exp.callback = elements.callback

    layout = row(plot, toggle, elements, column(z, v_exp))
    return _plot_to_json(layout)
Exemplo n.º 31
0
def photometry_plot(source_id):
    """Create scatter plot of photometry for source.

    Parameters
    ----------
    source_id : int
        ID of source to be plotted.

    Returns
    -------
    (str, str)
        Returns (docs_json, render_items) json for the desired plot.
    """
    color_map = {'ipr': 'yellow', 'rpr': 'red', 'g': 'green'}

    data = pd.read_sql(
        DBSession().query(
            Photometry,
            Telescope.nickname.label('telescope')).join(Instrument).join(
                Telescope).filter(Photometry.source_id == source_id).statement,
        DBSession().bind)
    if data.empty:
        return None, None, None

    for col in ['mag', 'e_mag', 'lim_mag']:
        # TODO remove magic number; where can this logic live?
        data.loc[np.abs(data[col]) > 90, col] = np.nan
    data['color'] = [color_map.get(f, 'black') for f in data['filter']]
    data['label'] = [
        f'{t} {f}-band' for t, f in zip(data['telescope'], data['filter'])
    ]
    data['observed'] = ~np.isnan(data.mag)
    split = data.groupby(['label', 'observed'])

    plot = figure(plot_width=600,
                  plot_height=300,
                  active_drag='box_zoom',
                  tools='box_zoom,wheel_zoom,pan,reset',
                  y_range=(np.nanmax(data['mag']) + 0.1,
                           np.nanmin(data['mag']) - 0.1))
    model_dict = {}
    for i, ((label, is_obs), df) in enumerate(split):
        key = ("" if is_obs else "un") + 'obs' + str(i // 2)
        model_dict[key] = plot.scatter(
            x='observed_at',
            y='mag' if is_obs else 'lim_mag',
            color='color',
            marker='circle' if is_obs else 'inverted_triangle',
            fill_color='color' if is_obs else 'white',
            source=ColumnDataSource(df))
    plot.xaxis.axis_label = 'Observation Date'
    plot.xaxis.formatter = DatetimeTickFormatter(hours=['%D'],
                                                 days=['%D'],
                                                 months=['%D'],
                                                 years=['%D'])
    plot.toolbar.logo = None

    hover = HoverTool(tooltips=[('observed_at', '@observed_at{%D}'),
                                ('mag', '@mag'), ('lim_mag', '@lim_mag'),
                                ('filter', '@filter')],
                      formatters={'observed_at': 'datetime'})
    plot.add_tools(hover)

    toggle = CheckboxWithLegendGroup(labels=list(data.label.unique()),
                                     active=list(
                                         range(len(data.label.unique()))),
                                     colors=list(data.color.unique()))

    # TODO replace `eval` with Namespaces
    # https://github.com/bokeh/bokeh/pull/6340
    toggle.callback = CustomJS(args={
        'toggle': toggle,
        **model_dict
    },
                               code="""
        for (let i = 0; i < toggle.labels.length; i++) {
            eval("obs" + i).visible = (toggle.active.includes(i))
            eval("unobs" + i).visible = (toggle.active.includes(i));
        }
    """)

    layout = row(plot, toggle)
    return _plot_to_json(layout)
Exemplo n.º 32
0
def overview_tab(df, x_name, date_name, measure):

    def make_dataset(category_list, range_start, range_end):
        reduced = pd.DataFrame()
        for cat in category_list:
            subset = df[df[x_name] == cat]
            if (type(range_start) == int) or (type(range_start) == float):
                range_start = datetime.fromtimestamp(range_start / 1000)
                range_end = datetime.fromtimestamp(range_end / 1000)
            print(range_start, range_end)
            subset = subset[(subset[date_name] > range_start) & (subset[date_name] < range_end)]
            reduced = reduced.append(subset)
        temp = pd.DataFrame(zip(viridis(len(category_list)), category_list), columns=['color', x_name])
        reduced = pd.merge(reduced, temp, on = x_name)
        reduced = reduced.sort_values(by=date_name, ascending=True)
        return ColumnDataSource(reduced)

    def style(p):
        # Title
        p.title.align = 'center'
        p.title.text_font_size = '20pt'
        p.title.text_font = 'serif'

        # Axis titles
        p.xaxis.axis_label_text_font_size = '14pt'
        p.xaxis.axis_label_text_font_style = 'bold'
        p.yaxis.axis_label_text_font_size = '14pt'
        p.yaxis.axis_label_text_font_style = 'bold'

        # Tick labels
        p.xaxis.major_label_text_font_size = '12pt'
        p.yaxis.major_label_text_font_size = '12pt'

        p.xaxis.formatter = DatetimeTickFormatter(
            hours=["%d %B %Y"],
            days=["%d %B %Y"],
            months=["%d %B %Y"],
            years=["%d %B %Y"]
        )
        # Names in Angles
        p.xaxis.major_label_orientation = np.pi / 4
        return p

    def make_plot(src):
        # Create the blank plot
        p = figure(plot_width=1200, plot_height=700,
                   title=measure + ' vs ' + date_name,
                   x_axis_label=date_name, y_axis_label=measure)

        # p.line(src.data[date_name], src.data[measure], line_width=0.9, line_color='grey')
        # p.circle(src.data[date_name], src.data[measure], fill_color='grey', line_color= 'black')

        p.line(x = date_name, y = measure, source = src, line_width=0.9, line_color='grey')
        p.circle(x = date_name, y = measure, source = src, size = 10, fill_color='color', fill_alpha=0.75, line_color='black',
                 hover_fill_alpha=1.0, hover_fill_color='green')

        # Hover tool referring to our own data field using @ and
        # a position on the graph using $
        h = HoverTool(tooltips=[(x_name, '@' + x_name),
                                (measure, '@' + measure)])

        # Add the hover tool to the graph
        p.add_tools(h)

        # Style the plot
        p = style(p)
        return p

    def update(attr, old, new):
        categories_to_plot = [category_selection.labels[i] for i in category_selection.active]
        new_src = make_dataset(categories_to_plot, range_select.value[0], range_select.value[1])
        src.data.update(new_src.data)

    df = df.sort_values(by = date_name, ascending= True)

    available_categories = list(set(df[x_name]))

    category_selection = CheckboxGroup(labels=available_categories,
                                       active=[i for i in range(len(available_categories))])

    category_selection.on_change('active', update)

    # Initial categories and data source
    initial_categories = [category_selection.labels[i] for i in category_selection.active]

    # categories and colors
    range_select = DateRangeSlider(start=df[date_name].iloc[0], end=df[date_name].iloc[-1],
                                   value=(df[date_name].iloc[0], df[date_name].iloc[-1]),
                                    step=1, title='Time Window')
    range_select.on_change('value', update)

    # Initial categories and data source
    src = make_dataset(initial_categories, range_start = range_select.value[0], range_end = range_select.value[1])

    p = make_plot(src)


    # Put controls in a single element
    controls = WidgetBox(category_selection, range_select)
    # Create a row layout
    layout = row(controls, p)

    # Make a tab with the layout
    tab = Panel(child = layout, title = 'Overview')

    return tab
Exemplo n.º 33
0
    yr = slider.value
    #    x=x_select.value
    #   y=y_select.value
    #label axes of plot
    #    plot.xaxis.axis_label = x
    #    plot.yaxis.axis_label = y
    #set new final_df
    new_data = {
        'x': final_df.fertility[final_df['Year'] == yr],
        'y': final_df.life[final_df['Year'] == yr],
        'Country': final_df.Country[final_df['Year'] == yr],
        #           'pop'      : final_df.population[final_df['Year']==yr],
        'region': final_df.region[final_df['Year'] == yr],
    }
    #assign new_final_df to source.final_df
    source.data = new_data
    # Add title to figure: plot.title.text
    plot.title.text = 'Gapminder final_df for %d' % yr


# Attach the callback to the 'value' property of slider
slider.on_change('value', update_plot)

# Make a row layout of widgetbox(slider) and plot and add it to the current document
layout = row(widgetbox(slider), plot)
curdoc().add_root(layout)
#curdoc().title = 'GapMinder'

#

#saved as gapminder_slider.py
Exemplo n.º 34
0
    kdims = [x.value, y.value]

    opts, style = {}, {}
    opts['color_index'] = color.value if color.value != 'None' else None
    if size.value != 'None':
        opts['size_index'] = size.value
        opts['scaling_factor'] = (1./df[size.value].max())*200
    points = hv.Points(df, kdims=kdims, label=label).opts(plot=opts, style=style)
    return renderer.get_plot(points).state

def update(attr, old, new):
    layout.children[1] = create_figure()

x = Select(title='X-Axis', value='mpg', options=quantileable)
x.on_change('value', update)

y = Select(title='Y-Axis', value='hp', options=quantileable)
y.on_change('value', update)

size = Select(title='Size', value='None', options=['None'] + quantileable)
size.on_change('value', update)

color = Select(title='Color', value='None', options=['None'] + quantileable)
color.on_change('value', update)

controls = widgetbox([x, y, color, size], width=200)
layout = row(controls, create_figure())

curdoc().add_root(layout)
curdoc().title = "Crossfilter"
def density_tab(flights):

    # Dataset for density plot based on overall rating, range of overall rating,
    # and bandwidth for density estimation
    def make_dataset(carrier_list, range_start, range_end, bandwidth):

        xs = []
        ys = []
        colors = []
        labels = []

        for i, carrier in enumerate(carrier_list):
            subset = flights[flights['Country'] == carrier]
            subset = subset[subset['Overall Rating'].between(
                range_start, range_end)]

            kde = gaussian_kde(subset['Overall Rating'], bw_method=bandwidth)

            # Evenly space x values
            x = np.linspace(range_start, range_end, 100)
            # Evaluate pdf at every value of x
            y = kde.pdf(x)

            # Append the values to plot
            xs.append(list(x))
            ys.append(list(y))

            # Append the colors and label
            colors.append(airline_colors[i])
            labels.append(carrier)

        new_src = ColumnDataSource(data={
            'x': xs,
            'y': ys,
            'color': colors,
            'label': labels
        })

        return new_src

    def make_plot(src):
        p = figure(plot_width=700,
                   plot_height=700,
                   title='Density Plot of Overll Rating by Country',
                   x_axis_label='Overall Rating',
                   y_axis_label='Density')

        p.multi_line('x',
                     'y',
                     color='color',
                     legend='label',
                     line_width=3,
                     source=src)

        # Hover tool with next line policy
        hover = HoverTool(tooltips=[('Country', '@label'), ('points', '$x'),
                                    ('Density', '$y')],
                          line_policy='next')

        # Add the hover tool and styling
        p.add_tools(hover)

        p = style(p)

        return p

    def update(attr, old, new):
        # List of carriers to plot
        carriers_to_plot = [
            carrier_selection.labels[i] for i in carrier_selection.active
        ]

        # If no bandwidth is selected, use the default value
        if bandwidth_choose.active == []:
            bandwidth = None
        # If the bandwidth select is activated, use the specified bandwith
        else:
            bandwidth = bandwidth_select.value

        new_src = make_dataset(carriers_to_plot,
                               range_start=range_select.value[0],
                               range_end=range_select.value[1],
                               bandwidth=bandwidth)

        src.data.update(new_src.data)

    def style(p):
        # Title
        p.title.align = 'center'
        p.title.text_font_size = '20pt'
        p.title.text_font = 'serif'

        # Axis titles
        p.xaxis.axis_label_text_font_size = '14pt'
        p.xaxis.axis_label_text_font_style = 'bold'
        p.yaxis.axis_label_text_font_size = '14pt'
        p.yaxis.axis_label_text_font_style = 'bold'

        # Tick labels
        p.xaxis.major_label_text_font_size = '12pt'
        p.yaxis.major_label_text_font_size = '12pt'

        return p

    # Carriers and colors
    available_carriers = list(set(flights['Country']))
    available_carriers.sort()

    airline_colors = Category20_16
    airline_colors.sort()

    # Carriers to plot
    carrier_selection = CheckboxGroup(labels=available_carriers, active=[0, 1])
    carrier_selection.on_change('active', update)

    range_select = RangeSlider(start=0,
                               end=180,
                               value=(0, 120),
                               step=5,
                               title='points')
    range_select.on_change('value', update)

    # Initial carriers and data source
    initial_carriers = [
        carrier_selection.labels[i] for i in carrier_selection.active
    ]

    # Bandwidth of kernel
    bandwidth_select = Slider(start=0.1,
                              end=5,
                              step=0.1,
                              value=0.5,
                              title='Bandwidth for Density Plot')
    bandwidth_select.on_change('value', update)

    # Whether to set the bandwidth or have it done automatically
    bandwidth_choose = CheckboxButtonGroup(
        labels=['Choose Bandwidth (Else Auto)'], active=[])
    bandwidth_choose.on_change('active', update)

    # Make the density data source
    src = make_dataset(initial_carriers,
                       range_start=range_select.value[0],
                       range_end=range_select.value[1],
                       bandwidth=bandwidth_select.value)

    # Make the density plot
    p = make_plot(src)

    # Add style to the plot
    p = style(p)

    # Put controls in a single element
    controls = WidgetBox(range_select, bandwidth_select, bandwidth_choose,
                         carrier_selection)

    # Create a row layout
    layout = row(controls, p)

    # Make a tab with the layout
    tab = Panel(child=layout, title='Density Plot')

    return tab
Exemplo n.º 36
0
N = 10
x = np.linspace(0, 4 * np.pi, N)
y = np.sin(x)
options = dict(tools="", toolbar_location=None, plot_height=300, plot_width=300)

p1 = figure(title="Line (300 x 100)", **options)
p1.plot_height = 100
p1.line(x, y)

p2 = figure(title="Annular wedge (100 x 300)", title_location='right', **options)
p2.plot_width = 100
p2.annular_wedge(x, y, 10, 20, 0.6, 4.1, inner_radius_units="screen", outer_radius_units="screen")

p3 = figure(title="Bezier (300 x 300)", **options)
p3.bezier(x, y, x + 0.4, y, x + 0.1, y + 0.2, x - 0.1, y - 0.2)

p4 = figure(title="Quad (300 x 300)", **options)
p4.quad(x, x - 0.2, y, y - 0.2)

spacer_1 = Spacer(width=100, height=100)
spacer_2 = Spacer(width=300, height=100)
paragraph = Paragraph(text="We build up a grid plot manually. Try changing the mode yourself.")

MODE = 'fixed'
widgets = widgetbox([paragraph], sizing_mode=MODE)
row_1 = row([spacer_1, p1, spacer_2], sizing_mode=MODE)
row_2 = row([p2, p3, p4], sizing_mode=MODE)
layout = column([widgets, row_1, row_2], sizing_mode=MODE)

show(layout)
Exemplo n.º 37
0
    )
import distributed.bokeh

SIZING_MODE = 'scale_width'
WIDTH = 600

messages = distributed.bokeh.messages  # global message store

doc = curdoc()

task_stream = TaskStream(1000, sizing_mode=SIZING_MODE, width=WIDTH, height=300, clear_interval=10000)
doc.add_periodic_callback(lambda: task_stream.update(messages), messages['task-events']['interval'])

task_progress = TaskProgress(sizing_mode=SIZING_MODE, width=WIDTH, height=160)
doc.add_periodic_callback(lambda: task_progress.update(messages), 50)

memory_usage = MemoryUsage(sizing_mode=SIZING_MODE, width=WIDTH, height=60)
doc.add_periodic_callback(lambda: memory_usage.update(messages), 50)

resource_profiles = ResourceProfiles(sizing_mode=SIZING_MODE, width=WIDTH, height=80)
doc.add_periodic_callback(lambda: resource_profiles.update(messages), messages['task-events']['interval'])

layout = column(
    row(resource_profiles.root, sizing_mode=SIZING_MODE),
    row(memory_usage.root, sizing_mode=SIZING_MODE),
    row(task_stream.root, sizing_mode=SIZING_MODE),
    row(task_progress.root, sizing_mode=SIZING_MODE),
    sizing_mode=SIZING_MODE
)
doc.add_root(layout)
output_file("callback.html")

x = [random() for x in range(500)]
y = [random() for y in range(500)]

s1 = ColumnDataSource(data=dict(x=x, y=y))
p1 = figure(plot_width=400, plot_height=400, tools="lasso_select", title="Select Here")
p1.circle('x', 'y', source=s1, alpha=0.6)

s2 = ColumnDataSource(data=dict(x=[], y=[]))
p2 = figure(plot_width=400, plot_height=400, x_range=(0, 1), y_range=(0, 1),
            tools="", title="Watch Here")
p2.circle('x', 'y', source=s2, alpha=0.6)

s1.callback = CustomJS(args=dict(s2=s2), code="""
        var inds = cb_obj.selected.indices;
        var d1 = cb_obj.data;
        var d2 = s2.data;
        d2['x'] = []
        d2['y'] = []
        for (i = 0; i < inds.length; i++) {
            d2['x'].push(d1['x'][inds[i]])
            d2['y'].push(d1['y'][inds[i]])
        }
        s2.change.emit();
    """)

layout = row(p1, p2)

show(layout)
Exemplo n.º 39
0
def activity_details(local_time, activity_group_name):
    f'''
    # Activity Details: {local_time} ({activity_group_name})
    '''
    '''
    $contents
    '''
    '''
    ## Load Data
    
    Open a connection to the database and load the data we require.
    '''

    s = session('-v2')

    activity = std_activity_statistics(s,
                                       local_time=local_time,
                                       activity_group_name=activity_group_name)
    details = activity_statistics(s,
                                  'Climb %',
                                  ACTIVE_TIME,
                                  ACTIVE_DISTANCE,
                                  local_time=local_time,
                                  activity_group_name=activity_group_name)
    health = std_health_statistics(s)
    hr_zones = hr_zones_from_database(s, local_time, activity_group_name)
    f'''
    ## Activity Plots
    
    To the right of each plot of data against distance is a related plot of cumulative data
    (except the last, cadence, which isn't useful and so replaced by HR zones).
    Green and red areas indicate differences between the two dates. 
    Additional red lines on the altitude plot are auto-detected climbs.
    
    Plot tools support zoom, dragging, etc.
    '''

    output_file(filename='/dev/null')

    sp = comparison_line_plot(700,
                              200,
                              DISTANCE_KM,
                              MED_SPEED_KMH,
                              activity,
                              ylo=0)
    sp_c = cumulative_plot(200, 200, MED_SPEED_KMH, activity, ylo=0)

    el = comparison_line_plot(700,
                              200,
                              DISTANCE_KM,
                              ELEVATION_M,
                              activity,
                              x_range=sp.x_range)
    add_climbs(el, details, activity)
    el_c = cumulative_plot(200, 200, CLIMB_MS, activity)

    hri = comparison_line_plot(700,
                               200,
                               DISTANCE_KM,
                               HR_IMPULSE_10,
                               activity,
                               ylo=0,
                               x_range=sp.x_range)
    hri_c = cumulative_plot(200, 200, HR_IMPULSE_10, activity, ylo=0)

    hr = comparison_line_plot(700,
                              200,
                              DISTANCE_KM,
                              HEART_RATE_BPM,
                              activity,
                              x_range=sp.x_range)
    add_hr_zones(hr, activity, DISTANCE_KM, hr_zones)
    hr_c = cumulative_plot(200, 200, HEART_RATE_BPM, activity)

    pw = comparison_line_plot(700,
                              200,
                              DISTANCE_KM,
                              MED_POWER_ESTIMATE_W,
                              activity,
                              ylo=0,
                              x_range=sp.x_range)
    pw_c = cumulative_plot(200, 200, MED_POWER_ESTIMATE_W, activity, ylo=0)

    cd = comparison_line_plot(700,
                              200,
                              DISTANCE_KM,
                              MED_CADENCE,
                              activity,
                              ylo=0,
                              x_range=sp.x_range)
    hr_h = histogram_plot(200, 200, HR_ZONE, activity, xlo=1, xhi=5)

    show(
        gridplot([[el, el_c], [sp, sp_c], [hri, hri_c], [hr, hr_c], [pw, pw_c],
                  [cd, hr_h]]))
    '''
    ## Activity Maps
    '''

    map = map_plot(400, 400, activity)
    m_el = map_intensity_signed(200,
                                200,
                                activity,
                                GRADE_PC,
                                ranges=map,
                                power=0.5)
    m_sp = map_intensity(200, 200, activity, SPEED_KMH, ranges=map, power=2)
    m_hr = map_intensity(200, 200, activity, HR_IMPULSE_10, ranges=map)
    m_pw = map_intensity(200, 200, activity, MED_POWER_ESTIMATE_W, ranges=map)
    show(
        row(map,
            gridplot([[m_el, m_sp], [m_hr, m_pw]], toolbar_location='right')))
    '''
    ## Activity Statistics
    '''
    '''
    Active time and distance exclude pauses.
    '''

    details[[ACTIVE_TIME, ACTIVE_DISTANCE]].dropna(). \
        transform({ACTIVE_TIME: format_seconds, ACTIVE_DISTANCE: format_metres})
    '''
    Climbs are auto-detected and shown only for the main activity. They are included in the elevation plot above.
    '''

    if present(details, CLIMB_TIME):
        display(
            transform(
                details.filter(like='Climb').dropna(), {
                    CLIMB_TIME: format_seconds,
                    CLIMB_ELEVATION: format_metres,
                    CLIMB_DISTANCE: format_metres,
                    CLIMB_GRADIENT: format_percent,
                    CLIMB_POWER: format_watts,
                    CLIMB_CATEGORY: lambda x: x
                }))
    '''
    ## Health and Fitness
    '''

    fitness, fatigue = like(FITNESS_D_ANY,
                            health.columns), like(FATIGUE_D_ANY,
                                                  health.columns)
    colours = ['black'] * len(fitness) + ['red'] * len(fatigue)
    alphas = [1.0] * len(fitness) + [0.5] * len(fatigue)
    ff = multi_line_plot(900,
                         300,
                         TIME,
                         fitness + fatigue,
                         health,
                         colours,
                         alphas=alphas)
    xrange = ff.x_range if ff else None
    add_multi_line_at_index(ff,
                            TIME,
                            fitness + fatigue,
                            health,
                            colours,
                            alphas=alphas,
                            index=-1)
    atd = std_distance_time_plot(900, 200, health, x_range=ff.x_range)
    shr = multi_plot(
        900,
        200,
        TIME, [DAILY_STEPS, REST_HR],
        health, ['grey', 'red'],
        alphas=[1, 0.5],
        x_range=xrange,
        rescale=True,
        plotters=[bar_plotter(dt.timedelta(hours=20)),
                  dot_plotter()])
    add_band(shr,
             TIME,
             LO_REST_HR,
             HI_REST_HR,
             health,
             'red',
             alpha=0.1,
             y_range_name=REST_HR)
    show(column(ff, atd, shr))
Exemplo n.º 40
0
p1.x_range.callback = CustomJS(args=dict(source=source),
                               code=jscode % ('x', 'width'))
p1.y_range.callback = CustomJS(args=dict(source=source),
                               code=jscode % ('y', 'height'))

p2 = figure(title='See Zoom Window Here',
            x_range=(0, 100),
            y_range=(0, 100),
            tools='',
            plot_width=400,
            plot_height=400)
p2.scatter(x,
           y,
           radius=radii,
           fill_color=colors,
           fill_alpha=0.6,
           line_color=None)
rect = Rect(x='x',
            y='y',
            width='width',
            height='height',
            fill_alpha=0.1,
            line_color='black',
            fill_color='black')
p2.add_glyph(source, rect)

layout = row(p1, p2)

show(layout)
Exemplo n.º 41
0
    label1ya.text = "reduced to = " + str(np.around(100 * mp2[0],
                                                    decimals=2)) + "%"
    label50a.text = 'reduced to = ' + str(np.around(MA2, decimals=1))
    label75a.text = 'reduced to = ' + str(np.around(A72, decimals=1))
    label25a.text = 'reduced to = ' + str(np.around(A22, decimals=1))


for w in [AgeSlider, EventMortalitySlider]:
    w.on_change('value', update_data)

GenderRadioButtons.on_change('active', update_data)
FreqRadioButtons.on_change('active', update_data)

inputs = column(AgeSlider, EventMortalitySlider, FreqRadioButtons,
                GenderRadioButtons)

# read in html strings for header and footer
# with open ("LifeHeader.txt", "r") as myfile:
#    texttop=myfile.read()
with open("LifeFooter.txt", "r") as myfile:
    textbottom = myfile.read()

# divtop = Div(text=texttop, sizing_mode="scale_width")
divbottom = Div(text=textbottom, sizing_mode="scale_width")

# create the document
# curdoc().add_root(divtop)
curdoc().add_root(row(inputs, plot))
curdoc().add_root(divbottom)
curdoc().title = "LifeExpectancy"
Exemplo n.º 42
0
def tuning_tab(beam, acc):
    '''Tuning accelerator

	'''
    pre = PreText(text='''You can configure accelerator elements.''')
    element_button = RadioButtonGroup(
        labels=['Accels', 'Solenoids', 'Quadrupoles'], active=0)
    tune_button = Button(label='Tune', button_type="success")
    select = Select(options=[itm.name for itm in acc.Ez_beamline.values()])
    select_maxfield = Slider(start=-5.0, end=5.0,
				    		 step=0.1, value=0.0,
							 title='MaxField [MV/m]', format='0[.]0')

    line_source = ColumnDataSource(data={'z': [0, 0], 'x': [-0.1, 0.1]})
    field_source = ColumnDataSource(data={'z': acc.z, 'Fz': acc.Ez(acc.z)})
    field_plot = figure(x_axis_label='z [m]', y_axis_label='Ez [MV/m]',
                        width=330, height=210)
    field_plot.line('z', 'Fz', source=field_source, line_color='#3A5785',
                    line_alpha=0.7, line_width=1)

    envelope_plot = figure(x_axis_label='z [m]', y_axis_label='Envelope, x [m]',
                        width=650, height=250)
    envelope_source = ColumnDataSource(data={'z': acc.z, 'x': 0*acc.z,
                                             '-x': 0*acc.z})
    centroid_source = ColumnDataSource(data={'z': acc.z, 'x': 0*acc.z})
    envelope_plot.line('z', 'x', source=envelope_source, line_color='#3A5785',
                        line_alpha=0.7, line_width=1)
    envelope_plot.line('z', '-x', source=envelope_source, line_color='#3A5785',
                        line_alpha=0.7, line_width=1)
    envelope_plot.line('z', 'x', source=line_source, line_color='#3A5785',
                        line_alpha=0.1, line_width=10)
    envelope_plot.line('z', 'x', source=centroid_source, line_color='#3A5785',
                        line_alpha=0.7, line_width=1, line_dash=[3,5])

    controls = row(column(pre, element_button, select, select_maxfield, tune_button),
                   field_plot)
    tab = Panel(child=column(controls, envelope_plot), title='Tuning')

    def element_handler(new, acc=acc):
        if new == 0:
            select.options=[itm.name for itm in acc.Ez_beamline.values()]
            select_maxfield.start = -5.0
            select_maxfield.end = 5.0
            select_maxfield.step = 0.1
            if select.options == []:
                select_maxfield.value = 0.0
                select.value = ''
            else:
                select_maxfield.value = acc.Ez_beamline[select.options[0]].max_field
                select.value = [itm.name for itm in acc.Ez_beamline.values()][0]
            select_maxfield.format='0[.]0'
            select_maxfield.title = 'MaxField [MV/m]'
            field_source.data = {'z': acc.z, 'Fz': acc.Ez(acc.z)}
            field_plot.yaxis.axis_label = 'Ez [MV/m]'
        if new == 1:
            select.options=[itm.name for itm in acc.Bz_beamline.values()]
            select_maxfield.start = 0.000
            select_maxfield.end = 0.500
            select_maxfield.step = 0.001
            if select.options == []:
                select_maxfield.value = 0.000
                select.value = ''
            else:
                select_maxfield.value = acc.Bz_beamline[select.options[0]].max_field
                select.value = [itm.name for itm in acc.Bz_beamline.values()][0]
            select_maxfield.format='0[.]000'
            select_maxfield.title = 'MaxField [T]'
            field_source.data = {'z': acc.z, 'Fz': acc.Bz(acc.z)}
            field_plot.yaxis.axis_label = 'Bz [T]'
        if new == 2:
            select.options=[itm.name for itm in acc.Gz_beamline.values()]
            select_maxfield.start = -10.0
            select_maxfield.end = 10.0
            select_maxfield.step = 0.1
            if select.options == []:
                select_maxfield.value = 0.0
                select.value = ''
            else:
                select_maxfield.value = acc.Gz_beamline[select.options[0]].max_field
                select.value = [itm.name for itm in acc.Gz_beamline.values()][0]
            select_maxfield.format='0[.]0'
            select_maxfield.title = 'MaxField [T/m]'
            field_source.data = {'z': acc.z, 'Fz': acc.Gz(acc.z)}
            field_plot.yaxis.axis_label = 'Gz [T/m]'

    def update_select_maxfield(attrname, old, new, acc=acc):
        if new != '':
            if element_button.active == 0:
                select_maxfield.value = acc.Ez_beamline[new].max_field
                line_source.data = {'z': [acc.Ez_beamline[new].z0, acc.Ez_beamline[new].z0],
                                    'x': [-0.1, 0.1]}
            if element_button.active == 1:
                select_maxfield.value = acc.Bz_beamline[new].max_field
                line_source.data = {'z': [acc.Bz_beamline[new].z0, acc.Bz_beamline[new].z0],
                                    'x': [-0.1, 0.1]}
            if element_button.active == 2:
                select_maxfield.value = acc.Gz_beamline[new].max_field
                line_source.data = {'z': [acc.Gz_beamline[new].z0, acc.Gz_beamline[new].z0],
                                    'x': [-0.1, 0.1]}

    def tune_handler(new, beam=beam, acc=acc):
        if select.value != '':
            if element_button.active == 0:
                acc.Ez_beamline[select.value].max_field = select_maxfield.value
                acc.compile()
                field_source.data = {'z': acc.z, 'Fz': acc.Ez(acc.z)}
            if element_button.active == 1:
                acc.Bz_beamline[select.value].max_field = select_maxfield.value
                acc.compile()
                field_source.data = {'z': acc.z, 'Fz': acc.Bz(acc.z)}
            if element_button.active == 2:
                acc.Gz_beamline[select.value].max_field = select_maxfield.value
                acc.compile()
                field_source.data = {'z': acc.z, 'Fz': acc.Gz(acc.z)}

        beam.df['p2'] = beam.df['pz']*beam.df['pz'] + beam.df['px']*beam.df['px'] + beam.df['py']*beam.df['py']
        E = beam.df['p2'].mean()**0.5 - beam.type.mass*rp.c**2/rp.e/1e6
        I = np.sign(beam.type.charge) * beam.charge * rp.c / (beam.df['z'].max()-beam.df['z'].min())
        X = beam.df['x'].max()
        Y = beam.df['y'].max()
        Xp = beam.df['px'].max() / beam.df['pz'].max()
        Yp = beam.df['py'].max() / beam.df['pz'].max()
        X_off = beam.df['x'].mean()
        Y_off = beam.df['x'].mean()
        Xp_off = beam.df['px'].mean() / beam.df['pz'].max()
        Yp_off = beam.df['py'].mean() / beam.df['pz'].max()
        beta = beam.df['pz'].max() / (E + beam.type.mass*rp.c**2/rp.e/1e6)
        gamma = 1/(1-beta**2)**0.5
        df = beam.df
        df['xp'] = df['px']/df['pz']
        df['yp'] = df['py']/df['pz']
        df['xp2'] = df['xp']*df['xp']
        df['yp2'] = df['yp']*df['yp']
        df['x xp'] = df['x']*df['xp']
        df['y yp'] = df['y']*df['yp']
        df['x2'] = df['x']*df['x']
        df['y2'] = df['y']*df['y']
        df['rms x'] = df['x2'].mean()**0.5
        df['rms y'] = df['y2'].mean()**0.5
        df['rms x Emittance'] = (df['x2'].mean()*df['xp2'].mean() - df['x xp'].mean()**2)**0.5
        df['rms y Emittance'] = (df['y2'].mean()*df['yp2'].mean() - df['y yp'].mean()**2)**0.5
        Emitt_x = df['rms x Emittance'].max()*gamma*beta
        Emitt_y = df['rms y Emittance'].max()*gamma*beta
        kv_beam = kv.Beam(energy=E,
                         current=I,
                         radius_x=X,
                         radius_y=Y,
                         radius_xp=Xp,
                         radius_yp=Yp,
                         normalized_emittance_x=Emitt_x,
                         normalized_emittance_y=Emitt_y,
                         x=X_off, y=Y_off,
                         xp=Xp_off, yp=Yp_off,
                         charge=np.sign(beam.type.charge))
        kv_sim = kv.Simulation(kv_beam, acc)
        kv_sim.track()
        envelope_source.data = {'z': acc.z, 'x': kv_sim.envelope_x(acc.z),
                                '-x': -kv_sim.envelope_x(acc.z)}
        centroid_source.data = {'z': acc.z, 'x': kv_sim.centroid_x(acc.z)}

    element_button.on_click(element_handler)
    select.on_change('value', update_select_maxfield)
    tune_button.on_click(tune_handler)

    return tab
Exemplo n.º 43
0
from bokeh.io import output_file, show
from bokeh.layouts import row
from bokeh.plotting import figure

output_file("layout.html")

x = list(range(11))
y0 = x
y1 = [10 - i for i in x]
y2 = [abs(i - 5) for i in x]

# create a new plot
s1 = figure(width=250, plot_height=250, title=None)
s1.circle(x, y0, size=10, color="navy", alpha=0.5)

# create another one
s2 = figure(width=250, height=250, title=None)
s2.triangle(x, y1, size=10, color="firebrick", alpha=0.5)

# create and another
s3 = figure(width=250, height=250, title=None)
s3.square(x, y2, size=10, color="olive", alpha=0.5)

# put the results in a row
show(row(s1, s2, s3))
def get_thiel_analysis_plots(ulog, px4_ulog, db_data, vehicle_data,
                             link_to_main_plots):
    global dfdata, simsource, simsource_static, realsource, realsource_static, usimsource, ts1, ts2, x, y
    """
    get all bokeh plots shown on the Thiel analysis page
    :return: list of bokeh plots
    """
    def _resample(time_array, data, desired_time):
        """ resample data at a given time to a vector of desired_time """
        data_f = interp1d(time_array, data, fill_value='extrapolate')
        return data_f(desired_time)

    sim = False
    if link_to_main_plots.find("sim") is not -1:
        temp_link_to_main_plots = link_to_main_plots.replace('sim', '')
        sim = True

    if sim:
        print("do some sim stuff")
    else:
        print("do regular stuff")
        page_intro = """
    <p>
    This page shows the correspondance between a simulated and a real flight log.
    </p>
        """
        # curdoc().template_variables['title_html'] = get_heading_html(
        #     ulog, px4_ulog,db_data, None, [('Open Main Plots', link_to_main_plots,)],
        #     'Thiel Analysis') + page_intro
        curdoc().template_variables['title_html'] = get_heading_html(
            ulog,
            px4_ulog,
            db_data,
            None,
            additional_links=[(
                'Open Main Plots',
                link_to_main_plots,
            ), ("Open Matching Simulation Log", '/browse?search=sim')])

        # set up plots

        simsource = ColumnDataSource(data=dict(x=[], y=[]))
        simsource_static = ColumnDataSource(data=dict(x=[], y=[]))
        realsource = ColumnDataSource(data=dict(realx=[], realy=[]))
        realsource_static = ColumnDataSource(data=dict(realx=[], realy=[]))

        cur_dataset = ulog.get_dataset('vehicle_local_position')
        dfdata = pd.DataFrame(cur_dataset.data)
        print(dfdata['x'])
        keys = []
        data = ulog.data_list
        for d in data:
            data_keys = [f.field_name for f in d.field_data]
            data_keys.remove('timestamp')
            #        print (data_keys)
            keys.append(data_keys)

        t = cur_dataset.data['timestamp']
        x = cur_dataset.data['x']
        y = cur_dataset.data['y']

        usimsource = ColumnDataSource(data=dict(x=t, y=y))
        usimsource_static = ColumnDataSource(data=dict(x=t, y=y))

        simtools = 'xpan,wheel_zoom,xbox_select,reset'
        realtools = 'xpan,wheel_zoom,reset'

        ts1 = figure(plot_width=900,
                     plot_height=200,
                     tools=simtools,
                     x_axis_type='linear',
                     active_drag="xbox_select")
        ts1.line('x', 'y', source=simsource, line_width=2)
        ts1.circle('x',
                   'y',
                   size=1,
                   source=simsource_static,
                   color=None,
                   selection_color="orange")

        ts2 = figure(plot_width=900,
                     plot_height=200,
                     tools=realtools,
                     x_axis_type='linear')
        # to adjust ranges, add something like this: x_range=Range1d(0, 1000), y_range = None,
        # ts2.x_range = ts1.x_range
        ts2.line('realx', 'realy', source=realsource, line_width=2)
        ts2.circle('realx',
                   'realy',
                   size=1,
                   source=realsource_static,
                   color="orange")

        plots = []
        flight_mode_changes = get_flight_mode_changes(ulog)
        x_range_offset = (ulog.last_timestamp - ulog.start_timestamp) * 0.05
        x_range = Range1d(ulog.start_timestamp - x_range_offset,
                          ulog.last_timestamp + x_range_offset)

        # cur_dataset = {}
        # cur_dataset = ulog.get_dataset('vehicle_gps_position')

        # # x = cur_dataset.data['vehicle_local_position']
        # # y = cur_dataset.data['y']
        #     # FIXME: bokeh should be able to handle np.nan values properly, but
        # # we still get a ValueError('Out of range float values are not JSON
        # # compliant'), if x or y contains nan
        # non_nan_indexes = np.logical_not(np.logical_or(np.isnan(x), np.isnan(y)))
        # x = x[non_nan_indexes]
        # y = y[non_nan_indexes]

        # if check_if_all_zero:
        #     if np.count_nonzero(x) == 0 and np.count_nonzero(y) == 0:
        #         raise ValueError()

        # data_source = ColumnDataSource(data=dict(x=x, y=y))
        # data_set['timestamp'] = cur_dataset.data['timestamp']

        # plot positions

        #    datatype = Select(value='XY', options=DEFAULT_FIELDS)
        datatype = Select(value='XY', options=keys[0])

        datatype.on_change('value', sim_change)

        file_input = FileInput(accept=".ulg")
        file_input.on_change('value', upload_new_data_sim)
        file_input2 = FileInput(accept=".ulg")
        file_input2.on_change('value', upload_new_data_real)

        intro_text = Div(
            text="""<H2>Sim/Real Thiel Coefficient Calculator</H2>""",
            width=500,
            height=100,
            align="center")
        sim_upload_text = Paragraph(text="Upload a simulator datalog:",
                                    width=500,
                                    height=15)
        real_upload_text = Paragraph(
            text="Upload a corresponding real-world datalog:",
            width=500,
            height=15)
        choose_field_text = Paragraph(text="Choose a data field to compare:",
                                      width=500,
                                      height=15)
        #checkbox_group = CheckboxGroup(labels=["x", "y", "vx","vy","lat","lon"], active=[0, 1])

        simsource_static.selected.on_change('indices', simselection_change)

        # The below are in case you want to see the x axis range change as you pan. Poorly documented elsewhere!
        #ts1.x_range.on_change('end', lambda attr, old, new: print ("TS1 X range = ", ts1.x_range.start, ts1.x_range.end))
        #ts2.x_range.on_change('end', lambda attr, old, new: print ("TS2 X range = ", ts2.x_range.start, ts2.x_range.end))

        ts1.x_range.on_change(
            'end', lambda attr, old, new: change_sim_scale(ts1.x_range.start))
        ts2.x_range.on_change(
            'end', lambda attr, old, new: change_real_scale(ts2.x_range.start))

        # set up layout
        widgets = column(datatype, stats)
        sim_button = column(sim_reverse_button)
        real_button = column(real_reverse_button)
        main_row = row(widgets)
        series = column(ts1, sim_button, ts2, real_button)
        layout = column(main_row, series)

        # initialize
        update()
        curdoc().add_root(intro_text)

        curdoc().add_root(sim_upload_text)
        curdoc().add_root(file_input)
        curdoc().add_root(real_upload_text)
        curdoc().add_root(file_input2)
        curdoc().add_root(choose_field_text)
        curdoc().add_root(layout)
        curdoc().title = "Flight data"
        #        plot_config['custom_tools'] = 'xpan,wheel_zoom,xbox_select,reset'

        # Local position
        for axis in ['x', 'y', 'z']:
            data_plot = DataPlot(data,
                                 plot_config,
                                 'vehicle_local_position',
                                 y_axis_label='[m]',
                                 title='Local Position ' + axis.upper(),
                                 plot_height='small',
                                 x_range=x_range)
            data_plot.add_graph([axis],
                                colors2[0:1], [axis.upper() + ' Estimated'],
                                mark_nan=True)
            data_plot.change_dataset('vehicle_local_position_setpoint')
            data_plot.add_graph([axis],
                                colors2[1:2], [axis.upper() + ' Setpoint'],
                                use_step_lines=True)
            plot_flight_modes_background(data_plot, flight_mode_changes)

            if data_plot.finalize() is not None: plots.append(data_plot)

        x_range_offset = (ulog.last_timestamp - ulog.start_timestamp) * 0.05
        x_range = Range1d(ulog.start_timestamp - x_range_offset,
                          ulog.last_timestamp + x_range_offset)

    # exchange all DataPlots with the bokeh_plot

    jinja_plot_data = []
    for i in range(len(plots)):
        if plots[i] is None:
            plots[i] = column(param_changes_button,
                              width=int(plot_width * 0.99))
        if isinstance(plots[i], DataPlot):
            if plots[i].param_change_label is not None:
                param_change_labels.append(plots[i].param_change_label)

            plot_title = plots[i].title
            plots[i] = plots[i].bokeh_plot

            fragment = 'Nav-'+plot_title.replace(' ', '-') \
                .replace('&', '_').replace('(', '').replace(')', '')
            jinja_plot_data.append({
                'model_id': plots[i].ref['id'],
                'fragment': fragment,
                'title': plot_title
            })

    curdoc().template_variables['plots'] = jinja_plot_data
    return plots
Exemplo n.º 45
0
    # set to roughly extent of points
    x_range = Range1d(start=airports['x'].min() - 10000, end=airports['x'].max() + 10000, bounds=None)
    y_range = Range1d(start=airports['y'].min() - 10000, end=airports['y'].max() + 10000, bounds=None)

    # create plot and add tools
    p = figure(tools='wheel_zoom,pan', x_range=x_range, y_range=y_range, title=title)
    p.axis.visible = False
    hover_tool = HoverTool(tooltips=[("Name", "@name"), ("Elevation", "@elevation (m)")])
    p.add_tools(hover_tool)
    p.add_tile(tile_source)

    # create point glyphs
    p.circle(x='x', y='y', size=9, fill_color="#F46B42", line_color="#D2C4C1", line_width=1.5, source=points_source)
    return p

# create a tile source
tile_options = {}
tile_options['url'] = 'http://tile.stamen.com/terrain/{Z}/{X}/{Y}.png'
tile_options['attribution'] = """
    Map tiles by <a href="http://stamen.com">Stamen Design</a>, under
    <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>.
    Data by <a href="http://openstreetmap.org">OpenStreetMap</a>,
    under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.
    """
mq_tile_source = WMTSTileSource(**tile_options)

carto = plot(CARTODBPOSITRON, 'airports_map_cartodb.html')
mq = plot(mq_tile_source, 'airports_map.html')

show(row([carto, mq]))
Exemplo n.º 46
0
# Ein Schieberegler wird definiert
freq = Slider(title="freq", value=1.0, start=1, end=105, step=0.1)

# wir holen uns eine Datei für das logging
log = open('/tmp/bokeh.log', 'a')


# Diese Funktion soll gerufen werden, wenn der Schieberegler sich ändert ..
def update_data(attrname, old, new):
    k = freq.value
    x = np.linspace(0, X_MAX, N)
    y = np.sin(k * x)
    source.data = dict(x=x, y=y)
    # füge eine fiktive Berechnugns-Zeit von einer Sekunde ein
    sleep(1)
    # Wir schreiben den log
    log_line_template = "%s: attribute: %s, old: %s, new: %s\n"
    log_line = log_line_template % (time.time(), attrname, old, new)
    log.write(log_line)


# .. was hier verdrahtet wird
freq.on_change('value', update_data)

# Hier wird eine Box im Browser erzeut, welche den Schieberegler enthält
inputs = widgetbox(freq)

# Diese Box wir im HTML-Document mit dem Plot in einer Zeile ausgerichtet
curdoc().add_root(row(inputs, plot, width=800))
Exemplo n.º 47
0
xmenu = []
for param in r0.keys():
    for item in r0[param]:
        xmenu.append((item, item))
    xmenu.append(None)
xdrop = Dropdown(menu=xmenu[:-1], button_type='primary')
xdrop.on_change('value', update_xdrop)

# create the Panel and Tabs objects for setting up the investment parameters
panels = []
for param in r0.keys():
    panels.append(create_panel(param, r0[param]))
tabs = Tabs(tabs=panels, width=1000)

# create the app layout
top = row(fig, widgetbox(xdrop, width=300))
layout = column(top, tabs)

# update the document and initialize the app by setting the Dropdown value
curdoc().add_root(layout)
param0 = list(r0.keys())[0]
xdrop.value = list(r0[param0].keys())[0]








    hover.tooltips = [
        ("Observation Starts", "@RealStarts"),
        ("Duration in Minutes", "@Starts"),
        ("Observation Counts", "@RealCounts"),
        ("Bird's Name", "@Name"),
    ]
    p.add_tools(hover)

    return p


# =============================================================================================

#        Task5: draw the figure and add bokeh server for interactive visualization

# =============================================================================================

# call datasource_construction function to get the source
source = datasource_construct(df)

# call draw_plot function to create the plots
p = draw_plot(source)
layout = column(p, row(select_category, width=200))

# ======= using bokeh server to run the application ========
# reference: https://bokeh.pydata.org/en/latest/docs/user_guide/server.html
curdoc().add_root(layout)

# ======= optional: output the result file ========
output_file('dvc_exc2_skeleton.html')
Exemplo n.º 49
0
df=pd.DataFrame({'x':x,'y':y,'label':label})

source = ColumnDataSource(data=dict(x=df.x, y=df.y,label=df.label))

plot_figure = figure(title='Select',plot_height=450, plot_width=600,
              tools="save,reset", toolbar_location="below")

plot_figure.scatter('x', 'y', source=source, size=10,color='label')

select = Select(title="Filter plot by color:", value="All", options=["All", "Red", "Orange"])

def select_click(attr,old,new):
    active_select=select.value ##Getting radio button value

    # filter the dataframe with value in select
    if active_select!='All':
        selected_df=df[df['label']==active_select]
    else:
        selected_df=df.copy()

    source.data=dict(x=selected_df.x, y=selected_df.y,label=selected_df.label)


select.on_change('value',select_click)

layout=row(select, plot_figure)

curdoc().add_root(layout)
curdoc().title = "Select Bokeh Server"
Exemplo n.º 50
0
             color=c,
             size=sz,
             line_color="white",
             alpha=0.6,
             hover_color='white',
             hover_alpha=0.5)

    return p


def update(attr, old, new):
    layout.children[1] = create_figure()


x = Select(title='X-Axis', value='mpg', options=columns)
x.on_change('value', update)

y = Select(title='Y-Axis', value='hp', options=columns)
y.on_change('value', update)

size = Select(title='Size', value='None', options=['None'] + quantileable)
size.on_change('value', update)

color = Select(title='Color', value='None', options=['None'] + quantileable)
color.on_change('value', update)

controls = widgetbox([x, y, color, size], width=200)
layout = row(controls, create_figure())

curdoc().add_root(layout)
curdoc().title = "Crossfilter"
from bokeh.plotting import figure
from bokeh.layouts import row
from bokeh.io import save

def make_figure(output_backend):
    p = figure(plot_width=400,
               plot_height=400,
               output_backend=output_backend,
               title="Backend: %s" % output_backend)

    p.circle(x=[1, 2, 3], y=[1, 2, 3], radius=0.25, color="blue", alpha=0.5)
    p.annulus(x=[1, 2, 3], y=[1, 2, 3], inner_radius=0.1, outer_radius=0.20, color="orange")

    return p

canvas = make_figure("canvas")
webgl  = make_figure("webgl")
svg    = make_figure("svg")

save(row(canvas, webgl, svg))
def trend_chart(returns_series,
                compounding: bool = False,
                height: int = 350,
                width: int = 800):
    """Trend chart of the result using Bokeh.
    
    Parameters
    ----------
    returns_series : Pandas Series
        Series contains returns.
    
    compounding : bool, default False
        Whether returns are reinvested back into the account.
        
    height : int
        Height of the plot
        
    width : int
        Width of the plot
        
    Returns
    -------
    None
    """

    data = returns_series

    if compounding:
        cum = (data + 1).cumprod()
    else:
        cum = data.cumsum() + 1

    cum = pd.DataFrame(cum)
    source = ColumnDataSource(data=cum)

    p = figure(x_axis_type="datetime",
               title="Trend Line",
               plot_height=height,
               plot_width=width)
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_alpha = 0.5
    p.xaxis.axis_label = 'Time'
    p.yaxis.axis_label = 'Total Return'
    lines = []
    for i in range(len(cum.columns)):
        lines.append(
            p.line("Date",
                   cum.columns[i],
                   source=source,
                   line_width=2,
                   line_alpha=0.8,
                   line_color=Spectral10[i % 10],
                   legend_label=cum.columns[i],
                   muted_color=Spectral10[i % 10],
                   muted_alpha=0.1))

    p.legend.location = "top_left"
    p.legend.click_policy = "mute"

    LABELS = list(cum.columns)
    checkbox_group = CheckboxGroup(labels=LABELS)
    checkbox_group.active = list(range(len(LABELS)))

    code = """ for (var i = 0; i < lines.length; i++) {
                    lines[i].visible = false;
                    if (cb_obj.active.includes(i)){lines[i].visible = true;}
                }
           """
    callback = CustomJS(code=code, args={'lines': lines})
    checkbox_group.js_on_click(callback)

    layout = row(p, checkbox_group)
    show(layout)
from bokeh.charts import Histogram, output_file, show
from bokeh.layouts import row
from bokeh.sampledata.autompg import autompg as df

hist = Histogram(df, values='mpg', title="Auto MPG Histogram", plot_width=400)
hist2 = Histogram(df, values='mpg', label='cyl', color='cyl', legend='top_right',
                  title="MPG Histogram by Cylinder Count", plot_width=400)

output_file('hist.html')
show(row(hist, hist2))
                            ('Price', '@nadac_per_unit')],
                  formatters={'date': 'datetime'}))

    return plot


def update_plot(attrname, old, new):
    ver = vselect.value
    df1 = df.loc[df['ndc'] == int(new)]
    df1['date'] = pd.to_datetime(df1['date'])
    df1 = df1.set_index(['date'])
    df1.sort_index(inplace=True)
    newSource = ColumnDataSource(df1)
    source.data = newSource.data


df = pd.read_csv('plotting_data.csv')
ver = '54034808'  #Initial id number
cc = df['ndc'].astype(str).unique()  #select-menu options

vselect = Select(value=ver, title='Drug ID', options=sorted((cc)))

source = get_dataset(df, ver)
plot = make_plot(source, "Drug Prices")

vselect.on_change('value', update_plot)
controls = row(vselect)

curdoc().add_root(row(plot, controls))
show(plot)
Exemplo n.º 55
0
function1_input.on_change('value', input_change)
# text input for the second function to be convolved
function2_input = TextInput(value=convolution_settings.function1_input_init, title="my second function:")
function2_input.on_change('value', input_change)

# initialize plot
toolset = "crosshair,pan,reset,resize,save,wheel_zoom"
# Generate a figure container
plot = Figure(plot_height=400, plot_width=400, tools=toolset,
              title="Convolution of two functions",
              x_range=[convolution_settings.x_min_view, convolution_settings.x_max_view],
              y_range=[convolution_settings.y_min_view, convolution_settings.y_max_view])

# Plot the line by the x,y values in the source property
plot.line('x', 'y', source=source_function1, line_width=3, line_alpha=0.6, color='red', legend='function 1')
plot.line('x', 'y', source=source_function2, color='green', line_width=3, line_alpha=0.6, legend='function 2')
plot.line('x', 'y', source=source_result, color='blue', line_width=3, line_alpha=0.6, legend='convolution')
plot.scatter('x', 'y', source=source_xmarker, color='black')
plot.line('x', 'y', source=source_xmarker, color='black', line_width=3)
plot.patch('x', 'y_pos', source=source_overlay, fill_color='blue', fill_alpha=.2)
plot.patch('x', 'y_neg', source=source_overlay, fill_color='red', fill_alpha=.2)

# calculate data
update_data()

# lists all the controls in our app
controls = widgetbox(x_value_input, function_type, function1_input, function2_input, width=400)

# make layout
curdoc().add_root(row(plot, controls, width=800))
Exemplo n.º 56
0
    def readData(self, station):
        stationOutputFile = os.path.expanduser(
            f'~/Downloads/Weather/{station.ID}.csv')
        if os.path.exists(stationOutputFile):
            stationDF = pd.read_csv(stationOutputFile,
                                    index_col=0,
                                    parse_dates=True)
        else:
            interesingElements = ['PRCP', 'TMAX', 'TMIN', 'TAVG']
            stationDF = pd.DataFrame(columns=['StationId', 'Date'] +
                                     interesingElements)
            dataPath = os.path.expanduser(
                "~/Downloads/Weather/ghcnd_all.tar.gz")
            with tarfile.open(dataPath) as alltar:
                stationFileTarInfo = alltar.getmember(
                    f'ghcnd_all/{station.ID}.dly')
                with alltar.extractfile(stationFileTarInfo) as stationFile:
                    for line in stationFile:
                        line = line if isinstance(
                            line, str) else line.decode('utf-8')
                        element = line[17:21]
                        if element not in interesingElements:
                            continue

                        stationId = line[0:11]
                        startDate = datetime.date(int(line[11:15]),
                                                  int(line[15:17]), 1)

                        for day in range(1, 32):
                            startField = 21 + (day - 1) * 8
                            value = float(line[startField:startField +
                                               5].strip())
                            if value == -9999:
                                continue
                            fieldDate = startDate.replace(day=day)
                            stationDF.at[fieldDate, element] = value
            stationDF.to_csv(stationOutputFile)

        yearlyPrecip = stationDF.groupby(lambda p: p.year)['PRCP'].sum()
        print(yearlyPrecip)
        yearlyPlot = figure(
            title=f"Precipitation by calendar year: {station.NAME}",
            x_axis_label='Year',
            y_axis_label='mm * 100')
        yearlyPlot.line(yearlyPrecip.index, yearlyPrecip)

        monthlyPrecip = stationDF.groupby(
            lambda p: p.replace(day=1))['PRCP'].sum()
        monthlyPlot = figure(title=f"Precipitation by month: {station.NAME}",
                             x_axis_type="datetime",
                             x_axis_label='Month',
                             y_axis_label='mm * 100')
        monthlyPlot.line(monthlyPrecip.index, monthlyPrecip)

        monthlyComparisonPlot = figure(
            title=f"Precipitation by month comparison: {station.NAME}",
            x_axis_label='Month',
            y_axis_label='mm * 100')

        for year in range(stationDF.index.min().year,
                          stationDF.index.max().year + 1):
            yearData = stationDF[stationDF.index.year == year].groupby(
                lambda p: p.replace(day=1))['PRCP'].sum()
            monthlyComparisonPlot.line(yearData.index.month, yearData)

        stationRow = row(yearlyPlot, monthlyPlot, monthlyComparisonPlot)
        curdoc().add_root(stationRow)
Exemplo n.º 57
0
radii = np.random.random(size=N) * 1.5
colors = [
    "#%02x%02x%02x" % (int(r), int(g), 150) for r, g in zip(50+2*x, 30+2*y)
]

p = figure(tools="pan,wheel_zoom,zoom_in,zoom_out,reset")

p.scatter(x, y, radius=radii,
          fill_color=colors, fill_alpha=0.6,
          line_color=None)

# Add a div to display events and a button to trigger button click events

div = Div(width=1000)
button = Button(label="Button", button_type="success")
layout = column(button, row(p, div))


point_attributes = ['x','y','sx','sy']
pan_attributes = point_attributes + ['delta_x', 'delta_y']
pinch_attributes = point_attributes + ['scale']
wheel_attributes = point_attributes+['delta']

## Register Javascript event callbacks

# Button event
button.js_on_event(events.ButtonClick, display_event(div))

# LOD events
p.js_on_event(events.LODStart, display_event(div))
p.js_on_event(events.LODEnd,   display_event(div))
Exemplo n.º 58
0
columns = [
    TableColumn(field='x', title='Parameter'),
    TableColumn(field='y', title="Calibrated Value")
]

heading_para = Div(text="<font color ='#808080'><h4> Calibrated Parameters </h4></font><br><br>",\
              width = 800, height = 4)                                            # Set up heading for parameters

data_table2 = DataTable(source=source3, columns=columns, width=300,
                        height=120)  # Set up data table
#export_table= Button(label='Export Table', button_type="default")                # Create export table button
#export_table.on_click(exportParam)                                               # Export Function

#                                  Layout
widgetrow1 = widgetbox(spacing4, w_loadinput)
widgetcol2 = widgetbox(w_k1, w_k2, w_k3, w_k4, w_loadpara)
widgetcol3 = widgetbox(w_d1, w_d2, w_rfcf, w_ecorr)  #,w_savepara)
widget7 = widgetbox(heading_dis, data_table1, w_fn, spacing6, heading2)
widget5 = widgetbox(C_title, spacing2, spacing1, w_calibrate, heading_para,
                    data_table2)  #,export_table)
widget6 = widgetbox(RM_title, spacing3, spacing5, w_runmodel, heading_error,
                    data_table)
r = row(heading)
g = gridplot([[widget7, widgetrow1,
               prain], [widgetcol2, widgetcol3, pdischarge],
              [widget6, widget5, pstorage]])
w = column(r, g)
curdoc().add_root(w)
curdoc().title = "Sugawara GUI_sample1"
Exemplo n.º 59
0
label_fixation_button.on_click(label_fixation_cb)

remove_button = Button(label='remove')
remove_button.on_click(remove_cb)

trial_text = TextInput(value=str(trialNum))
trial_text.on_change('value', trial_text_cb)

nextTrial_button = Button(label='+trial')
nextTrial_button .on_click(next_trial_cb)

prevTrial_button= Button(label='-trial')
prevTrial_button.on_click(prev_trial_cb)

from bokeh.layouts import row
buttonBox = row(label_saccade_button, label_pursuit_button, label_fixation_button, remove_button)
trialSelectBox = row(prevTrial_button, trial_text, nextTrial_button)
#, sizing_mode='scale_width'

###########################################################################
# Get the HTML description header
from os.path import dirname, join
desc = bkM.Div(text=open(join(dirname(__file__), "description.html")).read(), width=800)

###########################################################################
# Add desc, figure and widgets to a layout
from bokeh.layouts import layout
layout = layout([[desc], [fig], [buttonBox],[trialSelectBox]])

###########################################################################
# Add layout to current document
Exemplo n.º 60
0
        "justify-content": "space-between",
        "display": "flex"
    })

div1 = Div(
    text=
    """Transformations: US Dollars, year over year growth rate and cumulative purchases in 2017 vs 2020.\n The later transformation cumulates Chinese purchases over each month in 2017 and 2020 and compares each. Because 2017 is the benchmark year for The Agreement, this measure provides a sense, for each product category, China's progress towards meeting their purchase commitments.\n
    """,
    width=400,
    background=background,
    style={
        "justify-content": "space-between",
        "display": "flex"
    })

controls = column(product_select, div0, level_select, div1)

height = int(1.95 * 533)
width = int(1.95 * 675)

layout = row(make_plot(),
             controls,
             sizing_mode="scale_height",
             max_height=height,
             max_width=width,
             min_height=int(0.25 * height),
             min_width=int(0.25 * width))

curdoc().add_root(layout)
curdoc().title = "us-china-products"