예제 #1
0
                 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)

paragraph = Paragraph(
    text=
    "We build up a grid plot manually. Try changing the mode of the plots yourself."
)

select = Select(title="Sizing mode",
                value="fixed",
                options=list(SizingMode),
                width=300)

plots = grid([[None, p1, None], [p2, p3, p4]])
layout = column(paragraph, select, plots)

select.js_link('value', p1, 'sizing_mode')
select.js_link('value', p2, 'sizing_mode')
select.js_link('value', p3, 'sizing_mode')
select.js_link('value', p4, 'sizing_mode')
select.js_link('value', layout, 'sizing_mode')

show(layout)
예제 #2
0
from bokeh.core.enums import SizingMode
from bokeh.layouts import column
from bokeh.models import Select
from bokeh.plotting import figure, show, output_file
from bokeh.sampledata.iris import flowers as df

colormap = {'setosa': 'red', 'versicolor': 'green', 'virginica': 'blue'}
colors = [colormap[x] for x in df.species]

plot = figure(sizing_mode="fixed")

plot.circle(df.petal_length, df.petal_width, color=colors, alpha=0.2, size=10)

select = Select(title="Sizing mode", value="fixed", options=list(SizingMode))
select.js_link('value', plot, 'sizing_mode')

layout = column(select, plot)
layout.sizing_mode = "stretch_both"  # set separately to avoid also setting children

output_file("sizing_mode.html", title="sizing_mode.py example")
show(layout)
예제 #3
0
    def main_gui_fnc(doc):

        # Make widgets
        plottype_list = ['Trends', '1D Distribution', '2D Distribution']
        plottype_dropdown = Select(title='Plot Type',
                                   value=plottype_list[0],
                                   options=plottype_list)

        trend_x_list = ['z', 't']
        trend_y_list = [
            'Beam Size', 'Bunch Length', 'Emittance (x,y)', 'Emittance (4D)',
            'Slice emit. (x,y)', 'Slice emit. (4D)', 'Charge', 'Energy',
            'Trajectory'
        ]
        trend_x_dropdown = Select(title='X axis',
                                  options=trend_x_list,
                                  value=trend_x_list[0])
        trend_y_dropdown = Select(title='Y axis',
                                  options=trend_y_list,
                                  value=trend_y_list[0])

        dist_list = ['t', 'x', 'y', 'px', 'py', 'pz']
        trend_slice_var_dropdown = Select(title='Slice variable',
                                          options=dist_list,
                                          value=dist_list[0])
        trend_slice_nslices_text = make_text_input(text_input_params,
                                                   'Number of slices',
                                                   min=5,
                                                   max=500,
                                                   value=50,
                                                   step=1)

        screen_z_dropdown = Select(title='Screen z (m)',
                                   options=screen_z_str_list,
                                   value=screen_z_str_list[0])
        dist_x_1d_dropdown = Select(title='X axis',
                                    options=dist_list,
                                    value=dist_list[0])
        dist_type_1d_list = [
            'Charge Density', 'Emittance X', 'Emittance Y', 'Emittance 4D',
            'Sigma X', 'Sigma Y'
        ]
        dist_type_1d_dropdown = Select(title='Y axis',
                                       options=dist_type_1d_list,
                                       value=dist_type_1d_list[0])
        nbin_1d_text = make_text_input(text_input_params,
                                       'Histogram bins',
                                       min=5,
                                       max=500,
                                       value=50,
                                       step=1)

        screen_z_dropdown_copy = Select(title='Screen z (m)',
                                        options=screen_z_str_list,
                                        value=screen_z_str_list[0])
        screen_z_dropdown_copy.js_link('value', screen_z_dropdown, 'value')
        screen_z_dropdown.js_link('value', screen_z_dropdown_copy, 'value')

        dist_x_dropdown = Select(title='X axis',
                                 options=dist_list,
                                 value=dist_list[1])
        dist_y_dropdown = Select(title='Y axis',
                                 options=dist_list,
                                 value=dist_list[2])
        dist_2d_type_list = ['Scatter', 'Histogram']
        dist2d_type_dropdown = Select(title='Plot method',
                                      options=dist_2d_type_list,
                                      value=dist_2d_type_list[1])
        scatter_color_list = [
            'density', 't', 'x', 'y', 'r', 'px', 'py', 'pz', 'pr'
        ]
        scatter_color_dropdown = Select(title='Scatter color variable',
                                        options=scatter_color_list,
                                        value=scatter_color_list[0])
        axis_equal_checkbox = CheckboxGroup(labels=['Enabled'], active=[])
        nbin_x_text = make_text_input(text_input_params,
                                      'Histogram bins, X',
                                      min=5,
                                      max=500,
                                      value=50,
                                      step=1)
        nbin_y_text = make_text_input(text_input_params,
                                      'Histogram bins, Y',
                                      min=5,
                                      max=500,
                                      value=50,
                                      step=1)

        cyl_copies_checkbox = CheckboxGroup(labels=['Enabled'], active=[])
        cyl_copies_text = make_text_input(text_input_params,
                                          'Number of copies',
                                          min=5,
                                          max=500,
                                          value=50,
                                          step=1)

        remove_correlation_checkbox = CheckboxGroup(labels=['Enabled'],
                                                    active=[])
        remove_correlation_n_text = make_text_input(text_input_params,
                                                    'Max polynomial power',
                                                    min=0,
                                                    max=10,
                                                    value=1,
                                                    step=1)
        remove_correlation_var1_dropdown = Select(title='Independent var (x)',
                                                  options=dist_list,
                                                  value=dist_list[1])
        remove_correlation_var2_dropdown = Select(title='Dependent var (y)',
                                                  options=dist_list,
                                                  value=dist_list[3])

        take_slice_checkbox = CheckboxGroup(labels=['Enabled'], active=[])
        take_slice_var_dropdown = Select(title='Slice variable',
                                         options=dist_list,
                                         value=dist_list[0])
        take_slice_nslices_text = make_text_input(text_input_params,
                                                  'Number of slices',
                                                  min=5,
                                                  max=500,
                                                  value=50,
                                                  step=1)
        take_slice_index_text = make_text_input(
            text_input_params,
            'Slice index',
            min=0,
            max=int(take_slice_nslices_text.value) - 1,
            value=0,
            step=1)

        trends_tab = column(add_label(trend_x_dropdown, widget_width),
                            add_label(trend_y_dropdown, widget_width),
                            add_label(trend_slice_var_dropdown, widget_width),
                            add_label(trend_slice_nslices_text, widget_width))

        dist_1d_tab = column(add_label(screen_z_dropdown, widget_width),
                             add_label(dist_x_1d_dropdown, widget_width),
                             add_label(dist_type_1d_dropdown, widget_width),
                             add_label(nbin_1d_text, widget_width))

        dist_2d_tab = column(
            add_label(screen_z_dropdown_copy, widget_width),
            add_label(dist2d_type_dropdown, widget_width),
            add_label(scatter_color_dropdown, widget_width),
            add_label(dist_x_dropdown, widget_width),
            add_label(dist_y_dropdown, widget_width),
            add_label(axis_equal_checkbox,
                      widget_width,
                      label='Equal scale axes'),
            add_label(nbin_x_text, widget_width),
            add_label(nbin_y_text, widget_width))

        postprocess_tab = column(
            add_label(cyl_copies_checkbox,
                      widget_width,
                      label='Cylindrical copies'),
            add_label(cyl_copies_text, widget_width),
            add_label(remove_correlation_checkbox,
                      widget_width,
                      label='Remove Correlation'),
            add_label(remove_correlation_n_text, widget_width),
            add_label(remove_correlation_var1_dropdown, widget_width),
            add_label(remove_correlation_var2_dropdown, widget_width),
            add_label(take_slice_checkbox,
                      widget_width,
                      label='Take slice of data'),
            add_label(take_slice_var_dropdown, widget_width),
            add_label(take_slice_index_text, widget_width),
            add_label(take_slice_nslices_text, widget_width))

        tab1 = Panel(child=trends_tab, title='Trends')
        tab2 = Panel(child=dist_1d_tab, title='1D Dist.')
        tab3 = Panel(child=dist_2d_tab, title='2D Dist.')
        tab4 = Panel(child=postprocess_tab, title='Postprocess')

        tabs = Tabs(tabs=[tab1, tab2, tab3, tab4])

        main_panel = column(row(add_label(plottype_dropdown, widget_width)),
                            tabs)

        # Main plotting function
        def create_plot():
            #Get current GUI settings
            plottype = plottype_dropdown.value.lower()
            trend_x = 'mean_' + trend_x_dropdown.value.lower()
            trend_y = get_trend_vars(trend_y_dropdown.value.lower())
            trend_slice_var = trend_slice_var_dropdown.value
            trend_slice_nslices = int(
                trend_slice_nslices_text.value
            )  #constrain_text_input(trend_slice_nslices_text, text_input_params)

            screen_z = float(screen_z_dropdown.value)
            dist_x_1d = dist_x_1d_dropdown.value
            dist_y_1d = dist_type_1d_dropdown.value.lower()
            nbins_1d = int(
                nbin_1d_text.value
            )  # constrain_text_input(nbin_1d_text, text_input_params)

            dist_x = dist_x_dropdown.value
            dist_y = dist_y_dropdown.value
            ptype = dist2d_type_dropdown.value.lower()

            scatter_color_var = scatter_color_dropdown.value.lower()
            is_trend = (plottype == 'trends')
            is_slice_trend = any(['slice' in yy for yy in trend_y])
            is_dist1d = (plottype == '1d distribution')
            is_dist2d = (plottype == '2d distribution')
            nbins = [int(nbin_x_text.value), int(nbin_y_text.value)]
            axis_equal = (0 in axis_equal_checkbox.active)

            cyl_copies_on = (0 in cyl_copies_checkbox.active) and (plottype !=
                                                                   'trends')
            cyl_copies = int(cyl_copies_text.value)

            remove_correlation = (0 in remove_correlation_checkbox.active
                                  ) and (plottype != 'trends')
            remove_correlation_n = int(remove_correlation_n_text.value)
            remove_correlation_var1 = remove_correlation_var1_dropdown.value
            remove_correlation_var2 = remove_correlation_var2_dropdown.value

            take_slice = (0 in take_slice_checkbox.active) and (plottype !=
                                                                'trends')
            take_slice_var = take_slice_var_dropdown.value
            take_slice_nslices = int(take_slice_nslices_text.value)
            text_input_params[
                take_slice_index_text.id]['max'] = take_slice_nslices - 1
            take_slice_index = int(take_slice_index_text.value)

            # Disable widgets
            trend_x_dropdown.disabled = not is_trend
            trend_y_dropdown.disabled = not is_trend
            trend_slice_var_dropdown.disabled = not is_slice_trend
            trend_slice_nslices_text.disabled = not is_slice_trend

            screen_z_dropdown.disabled = not is_dist1d
            dist_x_1d_dropdown.disabled = not is_dist1d
            dist_type_1d_dropdown.disabled = not is_dist1d
            nbin_1d_text.disabled = not is_dist1d

            screen_z_dropdown_copy.disabled = not is_dist2d
            dist2d_type_dropdown.disabled = not is_dist2d
            scatter_color_dropdown.disabled = not (is_dist2d
                                                   and ptype == 'scatter')
            dist_x_dropdown.disabled = not is_dist2d
            dist_y_dropdown.disabled = not is_dist2d
            axis_equal_checkbox.disabled = not is_dist2d
            nbin_x_text.disabled = not is_dist2d
            nbin_y_text.disabled = not is_dist2d

            if (is_trend):
                params = {}
                if (is_slice_trend):
                    params['slice_key'] = trend_slice_var
                    params['n_slices'] = trend_slice_nslices
                p = gpt_plot(gpt_data,
                             trend_x,
                             trend_y,
                             show_plot=False,
                             format_input_data=False,
                             **params)

            if (is_dist1d):
                ptype_1d = get_dist_plot_type(dist_y_1d)
                params = {}
                if (cyl_copies_on):
                    params['cylindrical_copies'] = cyl_copies
                if (remove_correlation):
                    params['remove_correlation'] = (remove_correlation_var1,
                                                    remove_correlation_var2,
                                                    remove_correlation_n)
                if (take_slice):
                    params['take_slice'] = (take_slice_var, take_slice_index,
                                            take_slice_nslices)
                p = gpt_plot_dist1d(gpt_data,
                                    dist_x_1d,
                                    screen_z=screen_z,
                                    plot_type=ptype_1d,
                                    nbins=nbins_1d,
                                    show_plot=False,
                                    format_input_data=False,
                                    **params)
            if (is_dist2d):
                params = {}
                params['color_var'] = scatter_color_var
                if (axis_equal):
                    params['axis'] = 'equal'
                if (cyl_copies_on):
                    params['cylindrical_copies'] = cyl_copies
                if (remove_correlation):
                    params['remove_correlation'] = (remove_correlation_var1,
                                                    remove_correlation_var2,
                                                    remove_correlation_n)
                if (take_slice):
                    params['take_slice'] = (take_slice_var, take_slice_index,
                                            take_slice_nslices)
                p = gpt_plot_dist2d(gpt_data,
                                    dist_x,
                                    dist_y,
                                    screen_z=screen_z,
                                    plot_type=ptype,
                                    nbins=nbins,
                                    show_plot=False,
                                    format_input_data=False,
                                    **params)

            p.width = plot_area_width
            return p

        gui = row(main_panel, create_plot())
        doc.add_root(gui)

        #callback functions
        def just_redraw(attr, old, new):
            gui.children[1] = create_plot()

        def change_tab(attr, old, new):
            new_index = plottype_list.index(new)
            if (tabs.active < 3):
                tabs.active = new_index
            gui.children[1] = create_plot()

        # Assign callbacks
        plottype_dropdown.on_change('value', change_tab)
        trend_x_dropdown.on_change('value', just_redraw)
        trend_y_dropdown.on_change('value', just_redraw)
        trend_slice_var_dropdown.on_change('value', just_redraw)
        trend_slice_nslices_text.on_change('value', just_redraw)

        screen_z_dropdown.on_change('value', just_redraw)
        dist_x_1d_dropdown.on_change('value', just_redraw)
        dist_type_1d_dropdown.on_change('value', just_redraw)
        nbin_1d_text.on_change('value', just_redraw)

        dist_x_dropdown.on_change('value', just_redraw)
        dist_y_dropdown.on_change('value', just_redraw)
        dist2d_type_dropdown.on_change('value', just_redraw)
        scatter_color_dropdown.on_change('value', just_redraw)
        nbin_x_text.on_change('value', just_redraw)
        nbin_y_text.on_change('value', just_redraw)
        axis_equal_checkbox.on_change('active', just_redraw)

        cyl_copies_checkbox.on_change('active', just_redraw)
        cyl_copies_text.on_change('value', just_redraw)
        remove_correlation_checkbox.on_change('active', just_redraw)
        remove_correlation_n_text.on_change('value', just_redraw)
        remove_correlation_var1_dropdown.on_change('value', just_redraw)
        remove_correlation_var2_dropdown.on_change('value', just_redraw)
        take_slice_checkbox.on_change('active', just_redraw)
        take_slice_var_dropdown.on_change('value', just_redraw)
        take_slice_index_text.on_change('value', just_redraw)
        take_slice_nslices_text.on_change('value', just_redraw)
예제 #4
0
    update_legend_color_bar(select_feature.value, day)


def update_src_after_day_change(attr, old, new):
    day = ts_to_day(new)
    geosource.geojson = create_sample(day).to_json()


# def update_label_figures_after_feature_change(attr, old, new):
#     label_figures.text = new


TOOLTIPS = [('Область', '@ADM1_UA'),
            (select_feature.value, '@{' + str(select_feature.value) + '}')]

plot.add_tools(HoverTool(tooltips=TOOLTIPS))

tabs.on_change('active', update_tabs)

select_feature.on_change('value', update_color_mapper_and_legend_color_bar_after_feature_change)
select_feature.on_change('value', update_tooltips_after_feature_change)
select_feature.js_link('value', plot.title, 'text')

# select_feature.on_change('value', update_label_figures_after_feature_change)

slider_time.on_change('value_throttled', update_src_after_day_change)
slider_time.on_change('value_throttled', update_color_mapper_and_legend_color_bar_after_day_change)


curdoc().add_root(column(tabs))
curdoc().title = 'Ukraine | Hospitals | Supply'
예제 #5
0
from bokeh.core.enums import SizingMode
from bokeh.layouts import column
from bokeh.models import Select
from bokeh.plotting import figure, show, output_file
from bokeh.sampledata.iris import flowers as df

colormap = {'setosa': 'red', 'versicolor': 'green', 'virginica': 'blue'}
colors = [colormap[x] for x in df.species]

plot = figure(sizing_mode="fixed")

plot.circle(df.petal_length, df.petal_width, color=colors, alpha=0.2, size=10)

select = Select(title="Sizing mode", value="fixed", options=list(SizingMode))
select.js_link('value', plot, 'sizing_mode')

layout = column(select, plot)
layout.sizing_mode = "stretch_both" # set separately to avoid also setting children

output_file("sizing_mode.html", title="sizing_mode.py example")
show(layout)
예제 #6
0
options = dict(tools="", toolbar_location=None, plot_height=300, plot_width=300, sizing_mode="fixed")

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 = 200
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)

paragraph = Paragraph(text="We build up a grid plot manually. Try changing the mode of the plots yourself.")

select = Select(title="Sizing mode", value="fixed", options=list(SizingMode), width=300)

plots = grid([[None, p1, None], [p2, p3, p4]])
layout = column([paragraph, select, plots])

select.js_link('value', p1, 'sizing_mode')
select.js_link('value', p2, 'sizing_mode')
select.js_link('value', p3, 'sizing_mode')
select.js_link('value', p4, 'sizing_mode')
select.js_link('value', layout, 'sizing_mode')

show(layout)
예제 #7
0
def monitors(doc):
    ## Streaming Update Function
    def update():
        global cfg
        global s1
        global s2
        global s3

        df = get_vars(cfg['mon_fname'])
        s1.stream(df.to_dict(orient='list'), rollover=len(df))

        df = get_res(cfg['tra_fname'], cfg['resid_len'])
        if cfg['resid_len'] is None:
            s2.stream(df.to_dict(orient='list'), rollover=len(df))
        else:
            s2.stream(df.to_dict(orient='list'), rollover=cfg['resid_len'])
        s3.stream(get_prog(cfg['tra_fname']), rollover=1)

    def update_images():
        global cfg
        global s4
        s4.stream(get_img_data(cfg), rollover=1)

    ## Backgroud Color Update Function
    def night_mode():
        if (pd.datetime.now().hour >= 19) or (pd.datetime.now().hour < 6):
            curdoc().theme = 'dark_minimal'
            #curdoc().template = 'dark.html'

        else:
            curdoc().theme = 'light_minimal'
            #curdoc().template = 'index.html'
            # THIS NEEDS TO BE A JINJA TYPE?
        ## Not sure why this doesn't work...
        #curdoc().template_variables.update(background='#BA55D3')

    global cfg

    ## Plotting Setup
    do_not_plot = [
        'iteration', 'time', 'iter_left', 'converged', 'relative_total_time',
        'relative_time_step'
    ]
    sizes = cfg['sizes'].tolist()
    colors = itertools.cycle(palette)
    colors_res = itertools.cycle(palette)
    hover = HoverTool()
    res_hover = HoverTool()
    if 'flow_time' in s1.data.keys():
        # Unsteady Flow (transient)
        x_opts = [('Flow Time', '@flow_time s'), ('Time Step', '@time_step')]
        x_var = 'flow_time'
    else:
        # Steady Flow
        x_opts = [('Iteration', '@iteration')]
        x_var = 'iteration'
    hover.tooltips = [('Variable', '$name'), ('Value', '$y'), *x_opts]
    res_hover.tooltips = [('Variable', '$name'), ('Value', '$y'),
                          ('Iteration', '@iteration')]

    ## Plot Residuals
    w, h = sizes.pop(0)
    res_plots = figure(tools="pan,wheel_zoom,box_zoom,undo,reset,save",
                       plot_width=w,
                       plot_height=h,
                       y_axis_type='log')
    res_plots.add_tools(res_hover)

    for var, color in zip(s2.data.keys(), colors_res):
        if var not in do_not_plot:
            res_plots.line('iteration',
                           var,
                           line_width=2,
                           source=s2,
                           color=color,
                           legend=var.replace('_', ' ').title(),
                           name=var.replace('_', ' ').title())

    res_plots.legend.location = "top_left"
    res_plots.legend.click_policy = "hide"

    ## Progress Bar
    prog_bar = figure(plot_width=300,
                      plot_height=25,
                      toolbar_location=None,
                      x_range=[0, 1])
    prog_bar.grid.visible = False
    prog_bar.axis.visible = False
    prog_bar.hbar_stack(['steps_complete', 'steps_left'],
                        y=1,
                        height=0.8,
                        color=("limegreen", "lightgrey"),
                        source=s3)
    prog_bar.text(0.5,
                  1,
                  text='text',
                  text_baseline="middle",
                  text_align="center",
                  text_color="white",
                  text_font_style="bold",
                  source=s3)

    ## Plot Monitor Variables
    variables = var_name_cleaner(cfg['variables'])
    if cfg['var_ylims']:
        ylims = cfg['var_ylims']
    else:
        ylims = len(variables) * [None]

    plots = [res_plots]
    for var, ylim, color in zip(variables, ylims, colors):
        w, h = sizes.pop(0)
        p = figure(tools="pan,wheel_zoom,box_zoom,undo,reset,save",
                   plot_width=w,
                   plot_height=h)
        # Link x ranges
        try:
            p.x_range = plots[1].x_range
        except:
            pass
        if ylim is not None:
            print(ylim)
            p.y_range = Range1d(*ylim)

        if isinstance(var, str):
            p.line(x_var,
                   var,
                   line_width=2,
                   source=s1,
                   color=color,
                   legend=var.replace('_', ' ').title(),
                   name=var.replace('_', ' ').title())
        elif isinstance(var, list) or isinstance(var, tuple):
            for y, color in zip(var, itertools.cycle(palette_2)):
                p.line(x_var,
                       y,
                       line_width=2,
                       source=s1,
                       color=color,
                       legend=y.replace('_', ' ').title(),
                       name=y.replace('_', ' ').title())

        p.add_tools(hover)
        p.legend.click_policy = "hide"
        p.legend.location = "top_left"
        plots.append(p)

    ## Legend Locations
    select = Select(value="top_left",
                    options=list(LegendLocation),
                    width=100,
                    height=25)
    [select.js_link('value', f.legend[0], 'location') for f in plots[1::]]

    ## Legend Visibility
    def legend_visibility(active):
        for n, plot in enumerate(plots):
            if n in active:
                plot.legend[0].visible = True
            else:
                plot.legend[0].visible = False

    legend_button_group = CheckboxButtonGroup(
        labels=['Legend ' + str(n) for n in range(0, len(plots))],
        active=[n for n in range(0, len(plots))],
        width=cfg['width'] - 400,
        height=25)
    legend_button_group.on_click(legend_visibility)

    ## Turn off all active tools (helps for mobile)
    #https://stackoverflow.com/questions/49282688/how-do-i-set-default-active-tools-for-a-bokeh-gridplot
    # THIS DOESNT @!#$#@ WORK
    for p in plots:
        p.toolbar.active_drag = None
        p.toolbar.active_scroll = None
        p.toolbar.active_tap = None

    ## Initialize Image Plots
    if cfg['img_folder']:
        try:
            img_basenames = cfg['images']
            tabs = [Panel(child=plots[0], title='Residuals')]
            for img in img_basenames:
                p = figure(plot_width=plots[0].width,
                           plot_height=plots[0].height,
                           x_range=(0, 1),
                           y_range=(0, 1))
                p.image_url(url=img, x='x', y='y', w='w', h='h', source=s4)
                tabs.append(Panel(child=p, title=img))
            plots[0] = Tabs(tabs=tabs)
        except:
            print('Cannot add images')

    ## Create Layout
    # This will split the flat arry where sizes sum to the width of the doc
    sizes = cfg['sizes']
    splits = 1 + np.where(np.cumsum(sizes[:, 0]) % cfg['width'] == 0)[0]
    layout = [
        x.tolist() for x in np.split(np.array(plots), splits) if len(x) > 0
    ]

    ## Build the Document
    #doc.template = 'dark.html'
    night_mode()
    doc.add_periodic_callback(update, cfg['polling_int'])
    if cfg['img_folder']:
        doc.add_periodic_callback(update_images, 1000 * 30)
    doc.add_periodic_callback(night_mode, 1000 * 60 * 10)
    doc.title = 'Fluent Monitors'

    #Panel(child=p, title=fname)
    #gps = gridplot([[prog_bar,select,legend_button_group],[layout]], toolbar_location=None)
    #doc.add_root(gps)

    doc.add_root(
        gridplot([[prog_bar, select, legend_button_group]],
                 toolbar_location=None))
    [doc.add_root(gridplot([row], toolbar_location='right')) for row in layout]