bokeh.plotting.curdoc

Here are the examples of the python api bokeh.plotting.curdoc taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

14 Examples 7

3 View Source File : uibokeh.py
License : Apache License 2.0
Project Creator : OpendTect

def setReady( runbutbar ):
  runbutbar['state'] = RunState.Ready
  runbutbar['run'].label = go_lbl
  runbutbar['run'].button_type = enums.ButtonType.success
  runbutbar['pause'].visible = False
  if 'cb' in runbutbar:
    cb = runbutbar.pop( 'cb' )
    curdoc().remove_periodic_callback( cb )

def setPaused( runbutbar ):

3 View Source File : dashboard.py
License : MIT License
Project Creator : pfnet-research

def _run():
    # type: () -> None

    # Please note that `_study` and `optuna.dashboard._study` are different here. Here, this module
    # is loaded inside Bokeh, and thus it is not `optuna.dashboard`, but `bk_script_????`.
    study = optuna.dashboard._study
    mode = optuna.dashboard._mode

    assert study is not None
    app = _DashboardApp(study, launch_update_thread=(mode == 'serve'))
    doc = bokeh.plotting.curdoc()
    app(doc)


if __name__.startswith('bk_script_'):

0 View Source File : detfl_iJO1366.py
License : Apache License 2.0
Project Creator : EPFL-LCSB

def plot_dynamics(model, time_data):

    bp.curdoc().clear()

    # time_data += model.solver.configuration.tolerances.feasibility

    p1 = bp.figure(y_axis_type = 'log')
    p2 = bp.figure(y_axis_type = 'log')
    p3 = bp.figure(y_axis_type = 'log')
    p4 = bp.figure(y_axis_type = 'log')
    pex = bp.figure()

    t = time_data.loc['t']

    vars_to_obs = ['MR_b4025', 'MR_b1779', 'EZ_rib', 'EZ_rnap']

    cmap = Category10[10]

    for e, the_var in enumerate(['S_EX_glc__D_e','S_EX_glyc_e','X']):
        plot_hist(p1, t, time_data, the_var, cmap[e])

    rev_glc = model.reactions.EX_glc__D_e.reverse_variable.name
    for e, the_var in enumerate(['ub_EX_glc__D_e', 'ub_EX_glyc_e',
                                 'act_EX_glc__D_e', 'act_EX_glyc_e',
                                 'mu']):
        shape = 'square' if the_var.startswith('act_') else 'circle'
        plot_hist(p2, t, time_data, the_var, cmap[e], marker=shape)

    glycolysis_enzymes = get_enzymes_of_subsystem(model, 'Glycolysis')
    ppp_enzymes = get_enzymes_of_subsystem(model, 'pentose phosphate')
    tca_enzymes = get_enzymes_of_subsystem(model, 'Citric Acid Cycle')


    for e, the_var in enumerate(vars_to_obs):
        plot_hist(p3, t, time_data, the_var, cmap[e])

    time_data.loc['glycolysis'] = get_prot_total(time_data, glycolysis_enzymes)
    time_data.loc['ppp'] = get_prot_total(time_data, ppp_enzymes)
    time_data.loc['tca'] = get_prot_total(time_data, tca_enzymes)
    plot_hist(p4, t, time_data, 'glycolysis', cmap[e+1])
    plot_hist(p4, t, time_data, 'ppp', cmap[e+2])
    plot_hist(p4, t, time_data, 'tca', cmap[e+3])

    effluxes = time_data.loc[ time_data.index.str.startswith('EX_')
                              & time_data.index.str.endswith('_e') ]

    effluxes['score'] = effluxes.std(axis=1) / effluxes.mean(axis=1)

    effluxes = effluxes.reindex(
        effluxes['score'].sort_values(ascending = False).index,
        axis=0)

    for e,(the_var, values) in enumerate(effluxes[:5].T.iteritems()):

        pex.line(t, values,
                 color = cmap[e],
                 line_width = 2,
                 legend=the_var)

    for p in [p1,p2,p3,p4,pex]:
        #     p.legend.location = 'top_left'
        p.output_backend = 'svg'

    gp = gridplot([[p1,p3],[p2,p4],[pex]])
    bp.output_file('plots/dETFL_cheby_glyc.html')
    bp.show(gp)
    export_svgs(gp, filename='plots/dETFL_cheby_glyc.svg')


def plot_hist(figure, t, time_data, the_var, color, marker='circle'):

0 View Source File : detfl_monod.py
License : Apache License 2.0
Project Creator : EPFL-LCSB

def plot_dynamics(model, time_data):

    bp.curdoc().clear()

    # time_data += model.solver.configuration.tolerances.feasibility

    p1  = bp.figure()#y_axis_type = 'log')
    p2  = bp.figure()#y_axis_type = 'log')
    p3  = bp.figure(y_axis_type = 'log')
    p4  = bp.figure(y_axis_type = 'log')
    ps  = bp.figure()
    px  = bp.figure()

    t = time_data.loc['t']

    vars_to_obs = ['MR_b4025', 'MR_b1779', 'EZ_rib', 'EZ_rnap']

    cmap = Category10[10]

    for e, the_var in enumerate(concentrations):
        plot_var(p1, t, time_data, the_var, cmap[e])

    for e, (the_flux, the_ub) in enumerate(flux_ubs):
        plot_ub (p2, t, time_data, the_ub  , color=cmap[e])
        plot_var(p2, t, time_data, the_flux, color=cmap[e])

    p2.legend.location = 'bottom_right'
    plot_var(p2,t,time_data, 'mu', color=cmap[e+1])

    plot_growth(px,t,time_data)

    glycolysis_enzymes = get_enzymes_of_subsystem(model, 'Glycolysis')
    ppp_enzymes = get_enzymes_of_subsystem(model, 'pentose phosphate')
    tca_enzymes = get_enzymes_of_subsystem(model, 'Citric Acid Cycle')


    for e, the_var in enumerate(vars_to_obs):
        plot_var(p3, t, time_data, the_var, cmap[e])

    time_data.loc['glycolysis',:] = get_prot_total(time_data, glycolysis_enzymes)
    time_data.loc['ppp',:] = get_prot_total(time_data, ppp_enzymes)
    time_data.loc['tca',:] = get_prot_total(time_data, tca_enzymes)
    plot_var(p4, t, time_data, 'glycolysis', cmap[e + 1])
    plot_var(p4, t, time_data, 'ppp', cmap[e + 2])
    plot_var(p4, t, time_data, 'tca', cmap[e + 3])

    effluxes = time_data.loc[ time_data.index.str.startswith('EX_')
                              & time_data.index.str.endswith('_e') ]

    effluxes['score'] = effluxes.std(axis=1) / effluxes.mean(axis=1)

    effluxes = effluxes.reindex(
        effluxes['score'].sort_values(ascending = False).index,
        axis=0)

    # for e,(the_var, values) in enumerate(effluxes[:5].T.iteritems()):
    #
    #     pex.line(t, values,
    #              color = cmap[e],
    #              line_width = 2,
    #              legend=the_var)

    plot_subsystems(ps,t,model,time_data)

    for p in [p1,p2,p3,p4,ps,px]:
        #     p.legend.location = 'top_left'
        p.output_backend = 'svg'

    gp = gridplot([[p1,p3],[p2,p4],[ps,px]])
    bp.output_file('plots/{}.html'.format(model_tag))
    bp.show(gp)
    export_svgs(gp, filename='plots/{}.svg'.format(model_tag))

def plot_var(p, t, time_data, the_var, color, **kwargs):

0 View Source File : plot_expression_va.py
License : Apache License 2.0
Project Creator : EPFL-LCSB

def plot_va(filename, tag, kind, color = DEFAULT_COLOR, orient = 'horizontal'):
    bp.curdoc().clear()

    title = verbose_kinds[kind] + ' variability analysis for {} iJO1366 model'\
                                    .format(tag)
    data = pd.read_csv(os.path.join(outputs_folder, filename), index_col = 0)

    if not data.columns[0] in ['minimum','maximum']:
        data.columns = ['minimum','maximum']

    data += 1e-9 # Resolution of the solver
    f = lambda x: np.sqrt(x[0]*x[1])
    # data['score'] = data.mean(axis=1)
    data['score'] = data.apply(f, axis=1)
    data.sort_values(by='score', ascending = False, inplace = True)
    data['y'] = range(len(data))
    data['name'] = data.index

    source = ColumnDataSource(data)

    xdr = DataRange1d()
    ydr = DataRange1d()

    _tools_to_show = 'box_zoom,pan,save,hover,reset,tap,wheel_zoom'


    if orient == 'vertical':
        p1 = bp.figure( title=title, x_range=xdr, y_range=ydr,
                        x_axis_type = 'log',
                        plot_width=600,
                        plot_height=1000,
                        tools=_tools_to_show,
                        # h_symmetry=False, v_symmetry=False,
                        min_border=0)
        glyph = HBar(y="y", right="maximum", left="minimum", height=0.9,
                     fill_color=color, fill_alpha=0.5,
                     line_color = None)
        p1.add_glyph(source, glyph)

        p1.circle(x='score', y='y', fill_color=color, line_color=None,
                  source=source)
        axis1 = p1.xaxis
        axis2 = p1.yaxis
    elif orient == 'horizontal':
        p1 = bp.figure(title=title, x_range=ydr, y_range=xdr,
                       y_axis_type='log',
                       plot_width=1000,
                       plot_height=600,
                       tools=_tools_to_show,
                       # h_symmetry=False, v_symmetry=False,
                       min_border=0)

        glyph = VBar(x="y", top="maximum", bottom="minimum", width=0.9,
                     fill_color=color, fill_alpha=0.5,
                     line_color=None)
        p1.add_glyph(source, glyph)

        p1.circle(y='score', x='y', fill_color=color, line_color=None,
                  source=source)
        axis1 = p1.yaxis
        axis2 = p1.xaxis
    else:
        raise ValueError("orient should be 'vertical' or 'horizontal'")

    # Fix ticks
    label_dict = {}
    for i, s in enumerate(data.index):
        label_dict[i] = s
    axis2.formatter = FuncTickFormatter(code="""
                                            var labels = %s;
                                            return labels[tick];
                                        """ % label_dict)
    axis1.axis_label = '[{}]'.format(verbose_kinds[kind])

    # p1.yaxis.ticker = [x for x in range(len(data))]

    hover = p1.select(dict(type=HoverTool))
    hover.tooltips = [(verbose_kinds[kind], "@name"),
                      ("min", "@minimum"),
                      ("max", "@maximum"),
                      ]
    hover.mode = 'mouse'


    path = os.path.join(plots_folder, 'va_' + filename)
    bp.output_file(path + '.html')
    bp.show(p1)
    p1.output_backend='svg'
    export_svgs(p1, filename=path+'.svg')
    bp.curdoc().clear()

    return data


if __name__ == '__main__':

0 View Source File : viz_constraint_matix.py
License : Apache License 2.0
Project Creator : EPFL-LCSB

def plot_spy_matrix(model, destination):

    nzs = pd.DataFrame(get_matrix_coo_gurobi(model),
                       columns=['row_idx',
                                'col_idx',
                                'coeff',
                                'var_name',
                                'var_type',
                                'cons_name'])

    nzs = add_color_group(nzs)
    nzs['row_idx'] *= -1

    bp.curdoc().clear()

    hover = HoverTool(tooltips=[("constraint name", "@cons_name"),
                                ("variable name", "@var_name"),
                                ("coefficient", "@coeff"),
                                ("(x,y)", "(@col_idx, @row_idx)"),
                                ("type", "@var_type"), ])

    p = bp.figure(width = 1000)
    p.add_tools(hover)

    legend_it = []

    for e, (subgroup, this_data) in enumerate(nzs.groupby('groups')):

        source = ColumnDataSource.from_df(this_data)

        # if this_data['var_type'].iloc[0] in ['I', 'B']:
        #     plot_fun = p.square
        # else:
        #     plot_fun = p.circle

        plot_fun = p.square
        c = plot_fun('col_idx', 'row_idx',
                     color = tableau20[e],
                     source = source,
                     size = 2,
                     alpha=1)

        legend_it.append((subgroup,[c]))

    legend = Legend(items=legend_it, location=(0, 0))
    legend.click_policy = "mute"

    p.add_layout(legend, 'right')

    bp.output_file(destination)
    bp.show(p)

    return p

0 View Source File : plotting.py
License : Apache License 2.0
Project Creator : EPFL-LCSB

def summarize_model(model,time_data,groups,
                    output_path='.', model_tag='', backend ='png'):

    summary_plots = dict()
    detailed_plots = dict()
    cleaned_groups = dict()

    # Cleanup missing vars
    for key, varnames in groups.items():
        cleaned_groups[key] = [x for x in varnames if x in time_data.index or x == 'total']

    groups = cleaned_groups
    total_groups = {k:v for k,v in groups.items() if 'total' in v and 'pathway_enz' in k}

    for key,data_type in groups.items():
        summary_plots[key] = make_summary_plots(model,time_data,key,data_type)

        detailed_plots[key] = make_detailed_plots(model,time_data,data_type,backend)

    summary_plots['growth'] = make_growth_plot(model,time_data)

    summary_plots['mass_ratios'] = plot_mass(model,time_data)

    if model is not None:
        summary_plots['subsystems'] = plot_subsystems(model,time_data)

    summary_plots['total'] = make_total_plot(model, time_data, total_groups)

    output_folder = join(output_path)#,model_tag)#+'_'+get_timestr())

    if not exists(output_folder):
        makedirs(output_folder)

    bp.curdoc().clear()
    bp.output_file(join(output_folder,'summary.html'), title = model_tag)

    for p in summary_plots.values():
        p.output_backend = backend

    bp.show(column(list(summary_plots.values())))

    for key,this_dp in detailed_plots.items():
        bp.curdoc().clear()
        bp.output_file(join(output_folder,'{}.html'.format(key)))
        for p in this_dp.children:
            try:
                p.output_backend = backend
            except AttributeError:
                # Fails for gridplots
                pass
                # from bokeh.layouts import GridBox
                # if isinstance(p,GridBox):
                #     p.children[0][0].output_backend = backend
                # else: # Toolbox bar etc..
                #     pass
        bp.show(this_dp)



def make_summary_plots(model, time_data, key, data_type, total=False):

0 View Source File : bokeh_server.py
License : MIT License
Project Creator : karlicoss

def bokeh_main():
    from random import random
    # create a plot and style its properties
    p = figure(x_range=(0, 100), y_range=(0, 100), toolbar_location=None)
    p.border_fill_color = 'black'
    p.background_fill_color = 'black'
    p.outline_line_color = None
    p.grid.grid_line_color = None

    # add a text renderer to our plot (no data yet)
    r = p.text(x=[], y=[], text=[], text_color=[], text_font_size="26px",
            text_baseline="middle", text_align="center")

    i = 0

    ds = r.data_source

    # create a callback that will add a number in a random location
    def callback():
        nonlocal i

        # BEST PRACTICE --- update .data in one step with a new dict
        new_data = dict()
        new_data['x'] = ds.data['x'] + [random()*70 + 15]
        new_data['y'] = ds.data['y'] + [random()*70 + 15]
        new_data['text_color'] = ds.data['text_color'] + [RdYlBu3[i%3]]
        new_data['text'] = ds.data['text'] + [str(i)]
        ds.data = new_data

        i = i + 1

    # add a button widget and configure with the call back
    button = Button(label="Press Me")
    button.on_click(callback)

    # put the button and plot in a layout and add to the document
    curdoc().add_root(column(button, p))


# todo autogenerate all plot tabs? maybe based on annotations?
def bokeh_main_2():

0 View Source File : bokeh_server.py
License : MIT License
Project Creator : karlicoss

def bokeh_main_2():
    import sys
    src = Path(__file__).absolute().parent / 'src'
    sys.path.insert(0, str(src))

    from bokeh.layouts import layout # type: ignore
    from bokeh.models.widgets import Tabs, Panel # type: ignore
    from bokeh.plotting import figure # type: ignore

    from dashboard.core.bokeh import test_scatter_matrix
    import holoviews as hv
    f1 = hv.render(test_scatter_matrix())

    f2 = figure()
    f2.circle([0,0,2],[4,-1,1])

    # todo need something more lazy?
    from dashboard.data import sleep_dataframe
    from dashboard.sleep import plot_sleep
    # TODO would be cool to display logs in the frontend and also currently evaluated function?
    # although pehaps it's easier to just always keep logs open?


    from bokeh.models.widgets import DateRangeSlider # type: ignore
    from datetime import date
    drs = DateRangeSlider(
        title="Date Range: ",
        start=date(2017, 1, 1),
        end=date.today(),
        value=(date(2017, 9, 7), date(2017, 10, 15)),
        step=1,
    )

    def update(attr, old, new):
        print(attr, old, new)

    from bokeh.models import CustomJS # type: ignore
    # todo see https://docs.bokeh.org/en/latest/docs/gallery/slider.html
    update_js = CustomJS(
        args=dict(drs=drs),
        code='''
console.log("HIIII");
'''
    )

    drs.on_change('value', update)
    drs.js_on_change('value', update_js)

    l1 = layout([[f1, drs]], sizing_mode='fixed')
    l2 = layout([[f2]], sizing_mode='fixed')
    tabs = Tabs(tabs=[
        Panel(child=l1            , title='This is Tab 1'  ),
        Panel(child=l2            , title='This is Tab 2'  ),
        # Panel(child=layout([[sp]]), title='Sleep dataframe'),
    ])

    curdoc().add_root(tabs)


def main():

0 View Source File : main.py
License : MIT License
Project Creator : MathOnco

def button_callback():
    
    theme_t = theme_select.value
    if(theme_t == 'black'):
        curdoc().theme= theme_black
    elif(theme_t == 'gray'):
        curdoc().theme= theme_gray
    elif(theme_t == 'dark blue'):
        curdoc().theme= theme_blue
        
    jk = create_figure(stack_montage_flag)
    layout.children[1] = jk[0]
    
    print('############')
    print('In Button callback')
    tsne3 = jk[1]
    print(type(tsne3))
    print(tsne3)
    

    file_name_hover = jk[2]
    print('############fnh in button callback')
    print('file_name_hover')
    print(file_name_hover)
    

 
    markers_single = jk[3]
    print('############')
    print(type(markers_single))
    print(markers_single)

    cluster_ms_list = jk[4]
    print('############')
    print(type(cluster_ms_list ))
    print(cluster_ms_list )

    p1_out = draw_tSNE_scatter(tsne3, file_name_hover, cluster_ms_list) 
    p1 = p1_out[0]
    p2 = p1_out[1]
    p3 = p1_out[2]
    p4 = p1_out[3] 
   
    source = p1_out[4] 
    
    tab1 = Panel(child=p1, title="Response")
    tab2 = Panel(child=p2, title="Treatment")
    tab3 = Panel(child=p3, title="Cluster Annotations")
    tab4 = Panel(child=p4, title="Patient id") 

    tabs = Tabs(tabs=[ tab1, tab2, tab3, tab4 ]) 
    layout.children[2] = tabs
    
    return([p,p1,p2,p3,p4,source,tabs]) 


############################################################################
### create_figure() collects the user choices from the GUI and          ####
### calls either the generate_stack_montage() for reading in            ####
### a single image or the generate_image_tSNE() for multiplexed images  ####
############################################################################



def create_figure(stack_montage_flag):

0 View Source File : simulate.py
License : MIT License
Project Creator : microsoft

    def simulate(self,
                 agents: List[Agent],
                 baseline_accuracy: float = None,
                 init_train_data_portion: float = 0.1,
                 pm_test_sets: list = None,
                 accuracy_plot_wait_s=2E5,
                 train_size: int = None, test_size: int = None,
                 filename_indicator: str = None
                 ):
        """
        Run a simulation.

        :param agents: The agents that will interact with the data.
        :param baseline_accuracy: The baseline accuracy of the model.
            Usually the accuracy on a hidden test set when the model is trained with all data.
        :param init_train_data_portion: The portion of the data to initially use for training. Must be [0,1].
        :param pm_test_sets: The test sets for the prediction market incentive mechanism.
        :param accuracy_plot_wait_s: The amount of time to wait in seconds between plotting the accuracy.
        :param train_size: The amount of training data to use.
        :param test_size: The amount of test data to use.
        :param filename_indicator: Path of the filename to create for the run.
        """

        assert 0   <  = init_train_data_portion  < = 1

        # Data to save.
        save_data = dict(agents=[asdict(a) for a in agents],
                         baselineAccuracy=baseline_accuracy,
                         initTrainDataPortion=init_train_data_portion,
                         accuracies=[],
                         balances=[],
                         )
        time_for_filenames = int(time.time())
        save_path = f'saved_runs/{time_for_filenames}-{filename_indicator}-simulation_data.json'
        model_save_path = f'saved_runs/{time_for_filenames}-{filename_indicator}-model.json'
        plot_save_path = f'saved_runs/{time_for_filenames}-{filename_indicator}.png'
        self._logger.info("Saving run info to \"%s\".", save_path)
        os.makedirs(os.path.dirname(save_path), exist_ok=True)

        # Set up plots.
        doc: Document = curdoc()
        doc.title = "DeCAI Simulation"

        plot = figure(title="Balances & Accuracy on Hidden Test Set",
                      )
        plot.width = 800
        plot.height = 600

        plot.xaxis.axis_label = "Time (days)"
        plot.yaxis.axis_label = "Percent"
        plot.title.text_font_size = '20pt'
        plot.xaxis.major_label_text_font_size = '20pt'
        plot.xaxis.axis_label_text_font_size = '20pt'
        plot.yaxis.major_label_text_font_size = '20pt'
        plot.yaxis.axis_label_text_font_size = '20pt'

        plot.xaxis[0].ticker = AdaptiveTicker(base=5 * 24 * 60 * 60)
        plot.xgrid[0].ticker = AdaptiveTicker(base=24 * 60 * 60)

        balance_plot_sources_per_agent = dict()
        good_colors = cycle([
            colors.named.green,
            colors.named.lawngreen,
            colors.named.darkgreen,
            colors.named.limegreen,
        ])
        bad_colors = cycle([
            colors.named.red,
            colors.named.darkred,
        ])
        for agent in agents:
            source = ColumnDataSource(dict(t=[], b=[]))
            assert agent.address not in balance_plot_sources_per_agent
            balance_plot_sources_per_agent[agent.address] = source
            if agent.calls_model:
                color = 'blue'
                line_dash = 'dashdot'
            elif agent.good:
                color = next(good_colors)
                line_dash = 'dotted'
            else:
                color = next(bad_colors)
                line_dash = 'dashed'
            plot.line(x='t', y='b',
                      line_dash=line_dash,
                      line_width=2,
                      source=source,
                      color=color,
                      legend=f"{agent.address} Balance")

        plot.legend.location = 'top_left'
        plot.legend.label_text_font_size = '12pt'

        # JavaScript code.
        plot.xaxis[0].formatter = FuncTickFormatter(code="""
        return (tick / 86400).toFixed(0);
        """)
        plot.yaxis[0].formatter = PrintfTickFormatter(format="%0.1f%%")

        acc_source = ColumnDataSource(dict(t=[], a=[]))
        if baseline_accuracy is not None:
            plot.ray(x=[0], y=[baseline_accuracy * 100], length=0, angle=0, line_width=2,
                     legend=f"Accuracy when trained with all data: {baseline_accuracy * 100:0.1f}%")
        plot.line(x='t', y='a',
                  line_dash='solid',
                  line_width=2,
                  source=acc_source,
                  color='black',
                  legend="Current Accuracy")

        @gen.coroutine
        def plot_cb(agent: Agent, t, b):
            source = balance_plot_sources_per_agent[agent.address]
            source.stream(dict(t=[t], b=[b * 100 / agent.start_balance]))
            save_data['balances'].append(dict(t=t, a=agent.address, b=b))

        @gen.coroutine
        def plot_accuracy_cb(t, a):
            acc_source.stream(dict(t=[t], a=[a * 100]))
            save_data['accuracies'].append(dict(t=t, accuracy=a))

        continuous_evaluation = not isinstance(self._decai.im, PredictionMarket)

        def task():
            (x_train, y_train), (x_test, y_test) = \
                self._data_loader.load_data(train_size=train_size, test_size=test_size)
            classifications = self._data_loader.classifications()
            x_train, x_test, feature_index_mapping = self._feature_index_mapper.map(x_train, x_test)
            x_train_len = x_train.shape[0]
            init_idx = int(x_train_len * init_train_data_portion)
            self._logger.info("Initializing model with %d out of %d samples.",
                              init_idx, x_train_len)
            x_init_data, y_init_data = x_train[:init_idx], y_train[:init_idx]
            x_remaining, y_remaining = x_train[init_idx:], y_train[init_idx:]

            save_model = isinstance(self._decai.im, PredictionMarket) and self._decai.im.reset_model_during_reward_phase
            self._decai.model.init_model(x_init_data, y_init_data, save_model)

            if self._logger.isEnabledFor(logging.DEBUG):
                s = self._decai.model.evaluate(x_init_data, y_init_data)
                self._logger.debug("Initial training data evaluation: %s", s)
                if len(x_remaining) > 0:
                    s = self._decai.model.evaluate(x_remaining, y_remaining)
                    self._logger.debug("Remaining training data evaluation: %s", s)
                else:
                    self._logger.debug("There is no more remaining data to evaluate.")

            self._logger.info("Evaluating initial model.")
            accuracy = self._decai.model.log_evaluation_details(x_test, y_test)
            self._logger.info("Initial test set accuracy: %0.2f%%", accuracy * 100)
            t = self._time()
            doc.add_next_tick_callback(
                partial(plot_accuracy_cb, t=t, a=accuracy))

            q = PriorityQueue()
            random.shuffle(agents)
            for agent in agents:
                self._balances.initialize(agent.address, agent.start_balance)
                q.put((self._time() + agent.get_next_wait_s(), agent))
                doc.add_next_tick_callback(
                    partial(plot_cb, agent=agent, t=t, b=agent.start_balance))

            unclaimed_data = []
            next_data_index = 0
            next_accuracy_plot_time = 1E4
            desc = "Processing agent requests"
            current_time = 0
            with tqdm(desc=desc,
                      unit_scale=True, mininterval=2, unit=" requests",
                      total=len(x_remaining),
                      ) as pbar:
                while not q.empty():
                    # For now assume sending a transaction (editing) is free (no gas)
                    # since it should be relatively cheaper than the deposit required to add data.
                    # It may not be cheaper than calling `report`.

                    if next_data_index >= len(x_remaining):
                        if not continuous_evaluation or len(unclaimed_data) == 0:
                            break

                    current_time, agent = q.get()
                    update_balance_plot = False
                    if current_time > next_accuracy_plot_time:
                        self._logger.debug("Evaluating.")
                        next_accuracy_plot_time += accuracy_plot_wait_s
                        accuracy = self._decai.model.evaluate(x_test, y_test)
                        doc.add_next_tick_callback(
                            partial(plot_accuracy_cb, t=current_time, a=accuracy))

                        if continuous_evaluation:
                            self._logger.debug("Unclaimed data: %d", len(unclaimed_data))
                            pbar.set_description(f"{desc} ({len(unclaimed_data)} unclaimed)")

                        with open(save_path, 'w') as f:
                            json.dump(save_data, f, separators=(',', ':'))
                        self._decai.model.export(model_save_path, classifications,
                                                 feature_index_mapping=feature_index_mapping)

                        if os.path.exists(plot_save_path):
                            os.remove(plot_save_path)
                        self.save_plot_image(plot, plot_save_path)

                    self._time.set_time(current_time)

                    balance = self._balances[agent.address]
                    if balance > 0 and next_data_index  <  len(x_remaining):
                        # Pick data.
                        x, y = x_remaining[next_data_index], y_remaining[next_data_index]

                        if agent.calls_model:
                            # Only call the model if it's good.
                            if random.random()  <  accuracy:
                                update_balance_plot = True
                                self._decai.predict(Msg(agent.address, agent.pay_to_call), x)
                        else:
                            if not agent.good:
                                y = 1 - y
                            if agent.prob_mistake > 0 and random.random()  <  agent.prob_mistake:
                                y = 1 - y

                            # Bad agents always contribute.
                            # Good agents will only work if the model is doing well.
                            # Add a bit of chance they will contribute since 0.85 accuracy is okay.
                            if not agent.good or random.random()  <  accuracy + 0.15:
                                value = agent.get_next_deposit()
                                if value > balance:
                                    value = balance
                                msg = Msg(agent.address, value)
                                try:
                                    self._decai.add_data(msg, x, y)
                                    # Don't need to plot every time. Plot less as we get more data.
                                    update_balance_plot = next_data_index / len(x_remaining) + 0.1  <  random.random()
                                    balance = self._balances[agent.address]
                                    if continuous_evaluation:
                                        unclaimed_data.append((current_time, agent, x, y))
                                    next_data_index += 1
                                    pbar.update()
                                except RejectException:
                                    # Probably failed because they didn't pay enough which is okay.
                                    # Or if not enough time has passed since data was attempted to be added
                                    # which is okay too because a real contract would reject this
                                    # because the smallest unit of time we can use is 1s.
                                    if self._logger.isEnabledFor(logging.DEBUG):
                                        self._logger.exception("Error adding data.")

                    if balance > 0:
                        q.put((current_time + agent.get_next_wait_s(), agent))

                    claimed_indices = []
                    for i in range(len(unclaimed_data)):
                        added_time, adding_agent, x, classification = unclaimed_data[i]
                        if current_time - added_time  <  self._decai.im.refund_time_s:
                            break
                        if next_data_index >= len(x_remaining) \
                                and current_time - added_time  <  self._decai.im.any_address_claim_wait_time_s:
                            break
                        balance = self._balances[agent.address]
                        msg = Msg(agent.address, balance)

                        if current_time - added_time > self._decai.im.any_address_claim_wait_time_s:
                            # Attempt to take the entire deposit.
                            try:
                                self._decai.report(msg, x, classification, added_time, adding_agent.address)
                                update_balance_plot = True
                            except RejectException:
                                if self._logger.isEnabledFor(logging.DEBUG):
                                    self._logger.exception("Error taking reward.")
                        elif adding_agent.address == agent.address:
                            try:
                                self._decai.refund(msg, x, classification, added_time)
                                update_balance_plot = True
                            except RejectException:
                                if self._logger.isEnabledFor(logging.DEBUG):
                                    self._logger.exception("Error getting refund.")
                        else:
                            try:
                                self._decai.report(msg, x, classification, added_time, adding_agent.address)
                                update_balance_plot = True
                            except RejectException:
                                if self._logger.isEnabledFor(logging.DEBUG):
                                    self._logger.exception("Error taking reward.")

                        stored_data = self._decai.data_handler.get_data(x, classification,
                                                                        added_time, adding_agent.address)
                        if stored_data.claimable_amount  < = 0:
                            claimed_indices.append(i)

                    for i in claimed_indices[::-1]:
                        unclaimed_data.pop(i)

                    if update_balance_plot:
                        balance = self._balances[agent.address]
                        doc.add_next_tick_callback(
                            partial(plot_cb, agent=agent, t=current_time, b=balance))

            self._logger.info("Done going through data.")
            if continuous_evaluation:
                pbar.set_description(f"{desc} ({len(unclaimed_data)} unclaimed)")

            if isinstance(self._decai.im, PredictionMarket):
                self._time.add_time(agents[0].get_next_wait_s())
                self._decai.im.end_market()
                for i, test_set_portion in enumerate(pm_test_sets):
                    if i != self._decai.im.test_reveal_index:
                        self._decai.im.verify_next_test_set(test_set_portion)
                with tqdm(desc="Processing contributions",
                          unit_scale=True, mininterval=2, unit=" contributions",
                          total=self._decai.im.get_num_contributions_in_market(),
                          ) as pbar:
                    finished_first_round_of_rewards = False
                    while self._decai.im.remaining_bounty_rounds > 0:
                        self._time.add_time(agents[0].get_next_wait_s())
                        self._decai.im.process_contribution()
                        pbar.update()

                        if not finished_first_round_of_rewards:
                            accuracy = self._decai.im.prev_acc
                            # If we plot too often then we end up with a blob instead of a line.
                            if random.random()  <  0.1:
                                doc.add_next_tick_callback(
                                    partial(plot_accuracy_cb, t=self._time(), a=accuracy))

                        if self._decai.im.state == MarketPhase.REWARD_RESTART:
                            finished_first_round_of_rewards = True
                            if self._decai.im.reset_model_during_reward_phase:
                                # Update the accuracy after resetting all data.
                                accuracy = self._decai.im.prev_acc
                            else:
                                # Use the accuracy after training with all data.
                                pass
                            doc.add_next_tick_callback(
                                partial(plot_accuracy_cb, t=self._time(), a=accuracy))
                            pbar.total += self._decai.im.get_num_contributions_in_market()
                            self._time.add_time(self._time() * 0.001)

                            for agent in agents:
                                balance = self._balances[agent.address]
                                market_bal = self._decai.im._market_balances[agent.address]
                                self._logger.debug("\"%s\" market balance: %0.2f   Balance: %0.2f",
                                                   agent.address, market_bal, balance)
                                doc.add_next_tick_callback(
                                    partial(plot_cb, agent=agent, t=self._time(), b=max(balance + market_bal, 0)))

                self._time.add_time(self._time() * 0.02)
                for agent in agents:
                    msg = Msg(agent.address, 0)
                    # Find data submitted by them.
                    data = None
                    for key, stored_data in self._decai.data_handler:
                        if stored_data.sender == agent.address:
                            data = key[0]
                            break
                    if data is not None:
                        self._decai.refund(msg, np.array(data), stored_data.classification, stored_data.time)
                        balance = self._balances[agent.address]
                        doc.add_next_tick_callback(
                            partial(plot_cb, agent=agent, t=self._time(), b=balance))
                        self._logger.info("Balance for \"%s\": %.2f (%+.2f%%)",
                                          agent.address, balance,
                                          (balance - agent.start_balance) / agent.start_balance * 100)
                    else:
                        self._logger.warning("No data submitted by \"%s\" was found."
                                             "\nWill not update it's balance.", agent.address)

                self._logger.info("Done issuing rewards.")

            accuracy = self._decai.model.log_evaluation_details(x_test, y_test)
            doc.add_next_tick_callback(
                partial(plot_accuracy_cb, t=current_time + 100, a=accuracy))

            with open(save_path, 'w') as f:
                json.dump(save_data, f, separators=(',', ':'))
            self._decai.model.export(model_save_path, classifications, feature_index_mapping=feature_index_mapping)

            if os.path.exists(plot_save_path):
                os.remove(plot_save_path)
            self.save_plot_image(plot, plot_save_path)

        doc.add_root(plot)
        thread = Thread(target=task)
        thread.start()

0 View Source File : rca.py
License : MIT License
Project Creator : smartyal

def rca(functionNode):
    logger = functionNode.get_logger()
    logger.info("==>>>> in rca (root cause analysis " + functionNode.get_browse_path())
    progressNode = functionNode.get_child("control").get_child("progress")
    progressNode.set_value(0.1)

    variables = functionNode.get_child("selectedVariables").get_leaves()
    tag = functionNode.get_child("selectedTags").get_value() #only one tag 
    annotations = functionNode.get_child("annotations").get_leaves()
    feature = functionNode.get_child("selectedFeatures").get_value()
    algo = functionNode.get_child("selectedAlgorithms").get_value()
    target = functionNode.get_child("selectedTarget").get_target()

    p=Progress(progressNode)
    p.set_divisor(len(annotations)/0.5)
    p.set_offset(0.1)
    #now create the data as x-y

    results = {"x":[],"y":[]}
    var = variables[0]
    #now iterate over all annotations of the matching type and create feature
    for idx,anno in enumerate(annotations):
        p.set_progress(idx)
        if (anno.get_child("type").get_value() == "time") and (tag in anno.get_child("tags").get_value()):
            startTime =anno.get_child("startTime").get_value()
            endTime = anno.get_child("endTime").get_value()
            data = var.get_time_series(startTime,endTime)
            #now create the feature
            feat = calc_feature(data["values"],feature)
            targetValue = get_target(target,(date2secs(startTime)+date2secs(endTime))/2)
            if feat and targetValue and numpy.isfinite(feat) and numpy.isfinite(targetValue):
                results["x"].append(feat)
                results["y"].append(targetValue)
            else:
                logger.warning(f"no result for {var.get_name} @ {startTime}, anno:{tag}, feat:{feat}, target: {target}")
    
    #now we have all the x-y


    progressNode.set_value(0.7)
    fig = figure(title = "x-y Correlation Plot "+var.get_name(),
            tools=[PanTool(), WheelZoomTool(),ResetTool(),SaveTool()],
            plot_height=300,
            x_axis_label=feature+"("+var.get_name()+") @ "+tag,
            y_axis_label=target.get_name())
    fig.toolbar.logo = None
    curdoc().theme = Theme(json=themes.darkTheme)
    fig.xaxis.major_label_text_color = themes.darkTickColor
    fig.yaxis.major_label_text_color = themes.darkTickColor
    
    
    fig.scatter(x=results["x"], y=results["y"], size=5, fill_color="#d9b100", marker="o")
    fileName = functionNode.get_child("outputFileName").get_value()
    filePath = os.path.join(myDir,'./../web/customui/'+fileName)
    progressNode.set_value(0.8)
    output_file(filePath,mode="inline")#inline: put the bokeh .js into this html, otherwise the default cdn will be taken, might cause CORS problems)
    save(fig)


    #print(results)

    return True
#
 

def data_cleaning(annotations,order=None,logger=None):

0 View Source File : rca.py
License : MIT License
Project Creator : smartyal

def rca2(functionNode):
    logger = functionNode.get_logger()
    logger.info("==>>>> in rca2 (root cause analysis " + functionNode.get_browse_path())
    progressNode = functionNode.get_child("control").get_child("progress")
    progressNode.set_value(0.1)
    m=functionNode.get_model()

    report = '  <  i>REPORT < /i> < br> < div style="font-size:85%">'

    annotations = functionNode.get_child("annotations").get_leaves()
    #order = ["Step"+str(no) for no in range(1,19)]
    #order = ["Phase"+str(no) for no in range(3,28)]
    order = functionNode.get_child("annotationsOrder").get_value()
    logger.debug("filtering by order")
    annotations = data_cleaning( annotations ,order = order,logger=logger) #Step1,Step2,...Step18 lsit of lists
    report+=(f"found {len(annotations)} valid processes  < br>")
    
    #for now, flatten them out
    annotations = [subprocess   for process in annotations for subprocess in process]

    algo = functionNode.get_child("selectedAlgorithm").get_value()
    target = functionNode.get_child("selectedTarget").get_target()

    progressNode.set_value(0.3)
    #now we are building up the table by iterating all the children in "selection"
    entries = functionNode.get_child("selection").get_children()

    table = {"target":[]}
    firstVariable = True

    for entry in entries:
        logger.debug(f"entry {entry.get_name()}")
        #each entry is a combination of variable, tags and feature
        vars = entry.get_child("selectedVariables").get_targets()
        tags = entry.get_child("selectedTags").get_value()
        features = entry.get_child("selectedFeatures").get_value()
        #for iterate over variables
        for var in vars:
            logger.debug(f"processing variable: {var.get_name()} with tags {tags} and features {features}")
            #columnName = var.get_name()+str(tags)+m.getRandomId()
            for tag in tags:
                row = 0
                #table[columnName]=[]# make a column
                for idx,anno in enumerate(annotations):
                    if anno.get_child("type").get_value() != "time":
                        continue
                    if tag in anno.get_child("tags").get_value():
                        startTime =anno.get_child("startTime").get_value()
                        endTime = anno.get_child("endTime").get_value()
                        data = var.get_time_series(startTime,endTime)["values"]
                        #we take only the values "inside" the annotation
                        if len(data)>2:
                            data =data[1:-1]
                        #now create the features
                        for feature in features:
                            feat = calc_feature(data,feature)
                            columnName = var.get_name()+"_"+tag+"_"+feature
                            if not columnName in table:
                                table[columnName]=[]
                            table[columnName].append(feat)
                        
                        targetValue = get_target(target,(date2secs(startTime)+date2secs(endTime))/2)
                        if targetValue:
                            if firstVariable:
                                #for the first variable we also write the target
                                table["target"].append(targetValue)
                            else:
                                #for all others we make sure we have the same target value for that case (sanity check)
                                if table["target"][row] != targetValue:
                                    logger.warning(f'problem target {table["target"][row]} !=> {targetValue}')
                            row=row+1
                        else:
                            logger.warning(f"no corrrect target value for {startTime} - {endTime}")
                 
                firstVariable = False
    #now we have the table, plot it
    import json
    #print(json.dumps(table,indent=2))
    progressNode.set_value(0.5)
    #try a model
     
    algo = functionNode.get_child("selectedAlgorithm").get_value()
    if algo=="lasso":   
        reg = linear_model.LassoCV()
        report +=" using lasso Regression with auto-hyperparams  < br>"
    else:
        #default
        report +=" using linear Regression  < br>"
        reg = linear_model.LinearRegression() #try rigde, lasso

    columnNames = []
    dataTable = []
    saveDict = {}
    for k,v in table.items():
        saveDict[k]=numpy.asarray(v,dtype=numpy.float64)
        if k=="target":
            continue
        dataTable.append(v)
        columnNames.append(k)

    fileName = functionNode.get_child("outputFileName").get_value()
    filePath = os.path.join(myDir,'./../web/customui/'+fileName.split(".")[0])
    numpy.savez(filePath, **saveDict)
    #for loading:
    # get = numpy.load(name+".npz")
    # for name in get.files:
    # data = get[name]

    dataTable = numpy.asarray(dataTable)
    x=dataTable.T
    scaler = StandardScaler()
    scaler.fit(x)
    x=scaler.transform(x)

    
    y=table["target"]
    x_train, x_test, y_train, y_test = train_test_split(x, y) 
    reg.fit(x_train,y_train)
     
 
    
    #print(reg.coef_)
    y_hat= reg.predict(x_test)
    y_repeat = reg.predict(x_train)
    #print(f"predict: {y_hat} vs real: {y_test}")

    #check over/underfitting
    r_train = r2_score(y_train, y_repeat)
    r_test = r2_score(y_test,y_hat)
    

    report+="R < sup>2 < /sup> train= %.4g, R < sup>2 < /sup> test = %.4g  < br>"%(r_train,r_test)


    pearsons = []
    for col in x.T:
        pearsons.append(pearsonr(col, y)[0])

    #and finally the correlations between y and yhat
    y_pearson_train = pearsonr(y_train, y_repeat)[0]
    y_pearson_test = pearsonr(y_test,y_hat)[0]

    report+="pearsonCorr y/y_hat train:%.4g , test:%.4g  < br>"%(y_pearson_train,y_pearson_test)
    
    report +="regression coefficients, pearsons correlations: < br>"
    for col,coef,pear in zip(columnNames,reg.coef_,pearsons):
        report+="    %s:%.4g,   %.4g  < br>"%(col,coef,pear)
 




    #write report
    progressNode.set_value(0.8)
    report+=" < div>"#close the style div
    functionNode.get_child("report").set_value(report)
    #make a plot
    hover1= HoverTool(tooltips=[ ( 'x,y','$x,$y')],mode='mouse')
    hover1.point_policy='snap_to_data'
    hover1.line_policy = "nearest"
    tools = [PanTool(), WheelZoomTool(),BoxZoomTool(),ResetTool(),SaveTool(),hover1]
    title = "prediction results on "+functionNode.get_child("selectedAlgorithm").get_value()
    fig = figure(title = title,tools=tools,plot_height=300,plot_width=400)
    fig.toolbar.logo = None
    

    curdoc().theme = Theme(json=themes.darkTheme)
    fig.xaxis.major_label_text_color = themes.darkTickColor
    fig.yaxis.major_label_text_color = themes.darkTickColor
    fig.xaxis.axis_label= target.get_name()
    fig.xaxis.axis_label_text_color = "white"
    fig.yaxis.axis_label="predicted Values for "+target.get_name()
    fig.yaxis.axis_label_text_color="white"
    fig.circle(y_train,y_repeat,size=4,line_color="white",fill_color="white",name="train",legend_label="train")
    fig.circle(y_test,y_hat,line_color="#d9b100",fill_color="#d9b100",size=4,name="test",legend_label="test")
    mini = min([min(y_train),min(y_repeat),min(y_test),min(y_hat)])
    maxi = max([max(y_train),max(y_repeat),max(y_test),max(y_hat)])
    
    fig.line([mini,maxi],[mini,maxi],line_color="grey",line_dash="dashed")

    fileName = functionNode.get_child("outputFileName").get_value()
    filePath = os.path.join(myDir,'./../web/customui/'+fileName)
    fig.legend.location = "top_left"
    output_file(filePath,mode="inline")
    save(fig)





    return True




def prepare_annos_filter(functionNode):

0 View Source File : varstatistics.py
License : MIT License
Project Creator : smartyal

def varstatistics(functionNode):
    logger = functionNode.get_logger()
    logger.info("==>>>> statistics " + functionNode.get_browse_path())
    progressNode = functionNode.get_child("control").get_child("progress")
    progressNode.set_value(0)
    #functionNode.get_child("control.signal").set_value(None)

    vars = functionNode.get_child("variable").get_targets()
    widget = functionNode.get_child("widget").get_target()
    bins = functionNode.get_child("bins").get_value()
    tags = functionNode.get_child("annotations").get_value()
    startTime = date2secs(widget.get_child("startTime").get_value())
    endTime = date2secs(widget.get_child("endTime").get_value())

    vars = {var.get_id():{"node":var} for var in vars}


    #first 30% progress:
    prog = Progress(progressNode)
    progressNode.set_value(0.1)
    prog.set_offset(0.1)
    #prog.set_divisor()
    
    if tags:
        allAnnoNodes = widget.get_child("hasAnnotation.annotations").get_leaves()
        allAnnos=[]
        prog.set_divisor(len(allAnnoNodes)/0.2)
        for index,node in enumerate(allAnnoNodes):
            prog.set_progress(index)
            if node.get_child("type").get_value()=="time":
                thisTags = node.get_child("tags").get_value()
                if any(tag in tags for tag in thisTags):
                    anno = {}
                    for child in node.get_children():
                        anno[child.get_name()]=child.get_value()
                    if date2secs(anno["startTime"])>=startTime and date2secs(anno["endTime"])  <  =endTime and (anno["startTime"] < anno["endTime"]):    #take this anno only if it is inside the current start/end time
                        allAnnos.append(anno)
        if allAnnos == []:
            give_up(functionNode,"no matching annotations in selected time")
            return False
    else:
        allAnnos=[]

    progressNode.set_value(0.3)

    

    logger.debug(f"statistics annotations to look at: {len(allAnnos)}")
    prog.set_offset(0.3)
    totalAnnos = max(len(allAnnos),1)
    totalCount = len(vars)*totalAnnos

    prog.set_divisor(totalCount/0.3)
    totalValids = 0
    for varIndex,var in enumerate(vars):
        info = vars[var]
        if tags:
            #iterate over all start and end times
            values = numpy.asarray([],dtype=numpy.float64)
            for annoIndex,anno in enumerate(allAnnos):
                thisValues = info["node"].get_time_series(anno["startTime"],anno["endTime"])["values"]
                values = numpy.append(values,thisValues)
                myCount = varIndex*totalAnnos+annoIndex
                prog.set_progress(myCount)
        else:
            values = info["node"].get_time_series(startTime,endTime)["values"]
    
        valids = numpy.count_nonzero(numpy.isfinite(values))
        totalValids+=valids
        hist, edges = numpy.histogram(values, bins=bins)
        hist=hist/len(values) #normalize
        info["hist"]=hist
        info["edges"]=edges

    #make a plot
    if totalValids == 0:
        give_up(functionNode,"all Variables are have no data in the time and annotations selected")
        return False

    progressNode.set_value(0.6)

    hover1= HoverTool(tooltips=[ ( 'x,y','$x,$y')],mode='mouse')
    hover1.point_policy='snap_to_data'
    hover1.line_policy = "nearest"

    tools = [PanTool(), WheelZoomTool(),BoxZoomTool(),ResetTool(),SaveTool(),hover1]




    title = "Statistics of "+str([info["node"].get_name() for var,info in vars.items()])
    if tags:
        title = title + " in annotation: "+ str(tags )
    
    fig = figure(title = title,tools=tools,plot_height=300)
    fig.toolbar.logo = None

    curdoc().theme = Theme(json=themes.darkTheme)
    fig.xaxis.major_label_text_color = themes.darkTickColor
    fig.yaxis.major_label_text_color = themes.darkTickColor
    
    for index,var in enumerate(vars):
        info = vars[var]
        col = themes.darkLineColors[index]
        hist = info["hist"]
        edges = info["edges"]

        fig.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:],
           fill_color=col, line_color=col, alpha=0.8,legend_label=info["node"].get_name())
    
    fig.legend.location = "top_left"
    fileName = functionNode.get_child("fileName").get_value()
    filePath = os.path.join(myDir,'./../web/customui/'+fileName)
    
    
    
    # now make the trend box plot, but only for tags
    # for each variable we create statistics for the annotations and prepare the data
    # {"node":Node(), "boxLower":[], "boxUpper", "mean", "limitUpper", "limitLower"}
    # 
    
    startTime = date2secs(widget.get_child("startTime").get_value()) #we only take tags that are inside the current zoom of the widgets
    endTime = date2secs(widget.get_child("endTime").get_value())
    
    boxPlots = []
    allTimes = []
    if tags:
        for index,var in enumerate(vars):
            info={"node":vars[var]["node"],"boxLower":[],"boxUpper":[],"median":[],"time":[],"limitUpper":[],"limitLower":[],"mean":[]}
            for anno in allAnnos:
                data = info["node"].get_time_series(anno["startTime"],anno["endTime"])
                if len(data["values"]):
                    data["values"] = data["values"][numpy.isfinite(data["values"])]
                    #remove the nan
                if len(data["values"]):

                    #make the statistics
                    info["time"].append(numpy.median(data["__time"])*1000)
                    allTimes.append(numpy.median(data["__time"])*1000)
                    info["limitLower"].append(numpy.quantile(data["values"],0.01))
                    info["limitUpper"].append(numpy.quantile(data["values"],0.99))
                    info["boxLower"].append(numpy.quantile(data["values"],0.25))
                    info["boxUpper"].append(numpy.quantile(data["values"],0.75))
                    info["median"].append(numpy.median(data["values"]))
                    info["mean"].append(numpy.mean(data["values"]))
            boxPlots.append(info)

        format = "%Y-%m-%d-T%H:%M:%S"
        custom = """var local = moment(value).tz('UTC'); return local.format();"""#%self.server.get_settings()["timeZone"]

        hover = HoverTool(
            tooltips=[ ( 'date','@x{%F}')],
            formatters={ '@x'        : CustomJSHover(code=custom)
            },
            mode='mouse'
        )
        hover.point_policy='snap_to_data'
        hover.line_policy = "nearest"
        tools = [PanTool(), BoxZoomTool(),WheelZoomTool(),ResetTool(),hover,SaveTool()]
    
        
        fig2 = figure(title = "trends",tools=tools,plot_height=300,x_axis_type='datetime')
        fig2.xaxis.major_label_text_color = themes.darkTickColor
        fig2.yaxis.major_label_text_color = themes.darkTickColor
    
        progressNode.set_value(0.7)    
        
        fig2.xaxis.formatter=DatetimeTickFormatter(years=format,days=format,months=format,hours=format,hourmin=format,minutes=format,minsec=format,seconds=format)
        fig2.toolbar.logo = None
        #fig2.line([1,2,3],[1,2,3])
        #calc with of vbars
        if len(allAnnos)>1:
            xTimesStart = min(allTimes)
            xTimesEnd = max(allTimes)
            width = (xTimesEnd-xTimesStart)/2/len(allAnnos)
        else:
            width = 1000000

        for index,info in enumerate(boxPlots):
            #each info is for one variable
            col = themes.darkLineColors[index]
            fig2.segment(info["time"],info["limitUpper"],info["time"],info["boxUpper"],line_color=col)
            fig2.segment(info["time"],info["limitLower"],info["time"],info["boxLower"],line_color=col)
            
            width =20
            #fig2.vbar(info["time"],width=width,bottom=info["median"],top=info["boxUpper"],fill_color=col,line_color="black",width_units='screen')
            #fig2.vbar(info["time"],width=width,bottom=info["boxLower"],top=info["median"],fill_color=col,line_color="black",width_units='screen')
            #upper box
            sizUpper = numpy.asarray(info["boxUpper"])-numpy.asarray(info["median"])
            medUpper = numpy.asarray(info["median"])+sizUpper/2
            fig2.rect(x=info["time"],y=medUpper,width_units='screen',width=20,height=sizUpper,fill_color=col,line_color="black")

            #lower box
            sizLower = numpy.asarray(info["median"])-numpy.asarray(info["boxLower"])
            medLower = numpy.asarray(info["median"])-sizLower/2
            fig2.rect(x=info["time"],y=medLower,width_units='screen',width=20,height=sizLower,fill_color=col,line_color="black")
           
            #sort data for line
            x = numpy.asarray(info["time"])
            y = numpy.asarray(info["mean"])
            order = numpy.argsort(x)
            x=x[order]
            y=y[order]
            fig2.line(x,y,line_color=col)
        
        progressNode.set_value(0.8)    
    else:
       #no fig2 
       pass


        

    
    
    
    
    output_file(filePath,mode="inline")#inline: put the bokeh .js into this html, otherwise the default cdn will be taken, might cause CORS problems
    if tags:
        save(layout([[fig],[fig2]]))
    else:
        save(fig)

    return True