Beispiel #1
0
    def create_objects(cls, securities):

        ranks = utils.get_pumps_rank()
        quotient_metrics = utils.get_quotient_metrics()
        ranks['quotient'] = quotient_metrics['quotient']

        foo = lambda x: utils.spam_counts.get(x, 0)
        ranks['spams'] = map(foo, ranks['symbol'])
        ranks = ranks.sort('quotient', ascending=False)

        cls._pre_filtered_ranks = {
            'All': {k: ranks[k]
                    for k in ranks.columns},
            'Stocks with Spam':
            dict(ranks[ranks['symbol'].isin(plugins.spam_counts.keys())].sort(
                'quotient', ascending=False)),
            'Stocks without Spam':
            dict(ranks[~ranks['symbol'].isin(plugins.spam_counts.keys())].sort(
                'quotient', ascending=False)),
        }

        source_stocks_rank = ColumnDataSource(
            cls._pre_filtered_ranks['Stocks with Spam'])
        table_stocks_rank = DataTable(source=source_stocks_rank,
                                      width=785,
                                      height=400,
                                      selectable=True,
                                      editable=True,
                                      columns=[
                                          TableColumn(field='symbol',
                                                      title='symbol',
                                                      editor=StringEditor()),
                                          TableColumn(field='quotient',
                                                      title='quotient',
                                                      editor=StringEditor()),
                                          TableColumn(field='rank',
                                                      title='rank',
                                                      editor=StringEditor()),
                                          TableColumn(field='spams',
                                                      title='spams',
                                                      editor=StringEditor()),
                                      ])

        callback = Callback(args={
            'tr': table_stocks_rank,
            'sr': source_stocks_rank
        },
                            code=callbacks.source_stocks_rank)
        source_stocks_rank.callback = callback
        return locals()
def draw_bokeh(vecs, sentences):
    """ Dimension reduction with PCA and plotting with bokeh """

    X = np.array([x["feature_vector"] for x in vecs])
    X_reduced = PCA(n_components=2).fit_transform(X)

    source = ColumnDataSource(data=dict(
        eigenv1=[x[0] for x in X_reduced],
        eigenv2=[x[1] for x in X_reduced],
        s=sentences,
    ))

    hover = HoverTool(tooltips=[("index",
                                 "$index"), ("(x,y)",
                                             "@eigenv1, @eigenv2)"), ("s",
                                                                      "@s")])

    p = figure(title="Guardia nacional",
               tools=[hover, ResetTool(), BoxSelectTool()])
    p.xaxis.axis_label = '1st eigenv'
    p.yaxis.axis_label = '2nd eigenv'
    p.circle('eigenv1',
             'eigenv2',
             size=10,
             fill_alpha=1,
             nonselection_fill_alpha=0.5,
             source=source)

    div = Div(width=400)
    layout = row(p, div)

    source.callback = CustomJS(args=dict(source=source,
                                         div=div,
                                         sentences=sentences),
                               code="""
        var inds = source.selected.indices
        div.text = ""
        for (var i = 0; i < sentences.length; i++) {
            if (inds.includes(i)) {
                div.text += '<p style="background-color:powderblue;">' + sentences[i] + "</p>"
            }
            else {
                div.text += "<p>" + sentences[i] + "</p>"
            }   
        }
    """)

    output_file("news.html", title="Sentence embedding example")

    show(layout)
Beispiel #3
0
    def create_objects(cls, securities):

        ranks = utils.get_pumps_rank()
        quotient_metrics = utils.get_quotient_metrics()
        ranks['quotient'] = quotient_metrics['quotient']

        foo = lambda x: utils.spam_counts.get(x, 0)
        ranks['spams'] = map(foo, ranks['symbol'])
        ranks = ranks.sort('quotient', ascending=False)

        cls._pre_filtered_ranks = {
            'All': {k: ranks[k] for k in ranks.columns},
            'Stocks with Spam': dict(ranks[ranks['symbol'].
                                     isin(plugins.spam_counts.keys())].
                                     sort('quotient', ascending=False)),
            'Stocks without Spam': dict(ranks[~ranks['symbol'].
                                        isin(plugins.spam_counts.keys())].
                                        sort('quotient', ascending=False)),
        }

        source_stocks_rank = ColumnDataSource(cls._pre_filtered_ranks['Stocks with Spam'])
        table_stocks_rank = DataTable(
            source=source_stocks_rank, width=785, height=400,
            selectable=True, editable=True,
            columns=[
                TableColumn(field='symbol', title='symbol', editor=StringEditor()),
                TableColumn(field='quotient', title='quotient', editor=StringEditor()),
                TableColumn(field='rank', title='rank', editor=StringEditor()),
                TableColumn(field='spams', title='spams', editor=StringEditor()),
            ])

        callback = Callback(
            args={'tr': table_stocks_rank, 'sr': source_stocks_rank},
            code=callbacks.source_stocks_rank
        )
        source_stocks_rank.callback = callback
        return locals()
Beispiel #4
0
    def create_objects(cls, symbol, df, securities):
        descr_box = Paragraph(text='content loading...')

        btn_close_loading = Button(label='Close Loading')
        dialog_loading = Dialog(
            title='loading', content=vplot(descr_box), name='loading_dialog',
            buttons=[btn_close_loading], visible=False)

        source_data = dict(df)
        main_source = ColumnDataSource(dict(df))
        source = ColumnDataSource(source_data)

        # TODO: REMOVE THIS COMMENTED CODE! IT'S JUST THE PREVIOUS
        # VERSION USED BEFORE NEW P&D Cached results and algorithm
        # get the cached results of the P&D algorithm computed with the
        # "default" configuration
        # intervals = utils.cached_pumps.get(symbol, pumps.to_dicts(((),(),(),(),(),())))
        # intervals['bottom'] = [0] * len(intervals['start'])
        # intervals['values'] = [max(df['price'])] * len(intervals['start'])
        #
        # intervals = pd.DataFrame(intervals)

        # new version
        stats = utils.get_symbols_cached_stats()[symbol]
        intervals = pd.DataFrame(stats)
        intervals['bottom'] = [0] * len(intervals['start'])
        intervals['values'] = [max(df['price'])] * len(intervals['start'])

        conv = lambda x: utils.to_seconds(pd.to_datetime(x))

        intervals = intervals[
            (pd.to_datetime(intervals['start']) > conv(config.date_range[0])) &
            (pd.to_datetime(intervals['start']) < conv(config.date_range[1]))
        ]

        # Create P&Ds intervals DataSource
        intervals_source = ColumnDataSource(intervals)
        source.tags = ['main_source']

        trends = utils.load_trends_data(symbol, start_date=min(df['dt']))
        trends_source = ColumnDataSource(trends)

        trades = Slider(
            title="trades", name='trades',
            value=0, start=0, end=124, step=1
        )

        # Selectors
        symbol = Select.create(
            options=securities, value=symbol, name='symbol', title=""
        )
        window_selector = Select.create(
            options=['---'], name='period_selector', title="Search intervals with:"
        )
        symbol_filter = Select.create(
            options=['All', 'Stocks with Spam', 'Stocks without Spam'],
            name='symbol_filter', title="Filter Symbols:",
            value='Stocks with Spam'
        )
        callback = Callback(
            args={'symbol_filter': symbol_filter,
                  'dialog_loading': dialog_loading},
            code=callbacks.symbol_filter
        )
        symbol_filter.callback = callback


        btn_detect_pumps = Button(label='Configure P&D Detection', name='config_pumps')

        main_tab = Panel(title="Main")
        tabs = Tabs()

        # Create STOCKS TABLE
        ranks = utils.get_pumps_rank()
        # quotient_metrics = utils.get_quotient_metrics()
        # ranks['quotient'] = quotient_metrics['quotient']

        foo = lambda x: utils.spams_count.get(x, 0)
        ranks['spams'] = map(foo, ranks['symbol'])
        ranks = ranks.sort(['spams', 'vol_quotient'], ascending=False)

        cls._pre_filtered_ranks = {
            'All': {k: ranks[k] for k in ranks.columns},
            'Stocks with Spam': dict(ranks[ranks['spams'] > 0].
                                     sort('vol_quotient', ascending=False)),
            'Stocks without Spam': dict(ranks[ranks['spams'] == 0].
                                        sort('vol_quotient', ascending=False)),
        }

        source_stocks_rank = ColumnDataSource(cls._pre_filtered_ranks['All'])


        table_stocks_rank = DataTable(
            source=source_stocks_rank, width=560, height=450,
            selectable=True, editable=True,
            columns=[
                TableColumn(field='symbol', title='symbol', width=130, editor=StringEditor()),
                TableColumn(field='vol_quotient', title='volume ratio', editor=StringEditor(),
                            default_sort='descending'),
                TableColumn(field='risk_score', title='risk', width=100, editor=StringEditor(),
                            default_sort='descending'),
                TableColumn(field='spams', title='spams', width=130, editor=StringEditor(),
                            default_sort='descending'),
            ])

        callback = Callback(args={'tr': table_stocks_rank, 'sr': source_stocks_rank, 'symb': symbol,
                                  'dialog_loading': dialog_loading},
                            code=callbacks.source_stocks_rank)
        source_stocks_rank.callback = callback

        return locals()
Beispiel #5
0
def make_dashboard(motors, xy_train, operating_earnings, maintenance_cost,
                   repair_cost, run_interval):

    #calculate revenue vs time dataframe
    print '...generating dashboard...'
    events = get_events(motors)
    events['earnings'] = 0.0
    events.loc[events.state == 'operating', 'earnings'] = operating_earnings
    events['expenses'] = 0.0
    events.loc[events.state == 'maintenance', 'expenses'] = maintenance_cost
    events.loc[events.state == 'repair', 'expenses'] = repair_cost
    money = events.groupby('Time').sum()[['earnings', 'expenses']]
    money['revenue'] = money.earnings - money.expenses
    money['cumulative_earnings'] = money.earnings.cumsum()
    money['cumulative_expenses'] = money.expenses.cumsum()
    money['cumulative_revenue'] = money.revenue.cumsum()
    #map the (P,T) decision surface
    T_min = 50
    T_max = 150
    P_min = 0
    P_max = 100
    T_axis = np.arange(T_min, T_max, 0.5)
    P_axis = np.arange(P_min, P_max, 0.5)
    x, y = np.meshgrid(T_axis, P_axis)
    ttf = np.zeros((len(P_axis), len(T_axis)))
    import copy
    m = copy.deepcopy(motors[0])
    for p_idx in np.arange(len(P_axis)):
        for t_idx in np.arange(len(T_axis)):
            m.Temp = T_axis[t_idx]
            m.Pressure = P_axis[p_idx]
            ttf[p_idx, t_idx] = m.predicted_time_to_fail()

    #plot decision surface
    from bokeh.plotting import figure, show, output_file, ColumnDataSource, vplot
    from bokeh.models import HoverTool, Callback
    from bokeh.io import vform
    output_file('dashboard.html', title='Smart Maintenance Dashboard')
    source = ColumnDataSource(data=dict(
        x=xy_train.Temp,
        y=xy_train.Pressure,
        ttf=xy_train.time_to_fail,
        size=0.6 * xy_train.time_to_fail,
    ))
    dec_fig = figure(x_range=[T_min, T_max],
                     y_range=[P_min, P_max],
                     title='SVM Decision Surface',
                     x_axis_label='Temperature',
                     y_axis_label='Pressure',
                     tools='box_zoom,reset,hover,crosshair',
                     width=600,
                     plot_height=600)
    dec_fig.title_text_font_size = '18pt'
    dec_fig.xaxis.axis_label_text_font_size = '14pt'
    dec_fig.yaxis.axis_label_text_font_size = '14pt'
    dec_fig.image(image=[-ttf],
                  x=[T_min],
                  y=[P_min],
                  dw=[T_max - T_min],
                  dh=[P_max - P_min],
                  palette='RdYlGn8')
    dec_fig.x('x',
              'y',
              size='size',
              source=source,
              fill_alpha=0.5,
              fill_color='navy',
              line_color='navy',
              line_width=1,
              line_alpha=0.5)
    hover = dec_fig.select(dict(type=HoverTool))
    hover.tooltips = [
        ("Temperature", "@x"),
        ("Pressure", "@y"),
        ("measured lifetime", "@ttf"),
    ]

    #plot earnings vs time
    source = ColumnDataSource(data=dict(
        t=money.index,
        earnings=money.cumulative_earnings / 1.e6,
        expenses=money.cumulative_expenses / 1.e6,
        revenue=money.cumulative_revenue / 1.e6,
        zero=money.cumulative_revenue * 0,
    ))
    earn_fig = figure(title='Cumulative Earnings & Expenses',
                      x_axis_label='Time',
                      y_axis_label='Earnings & Expenses    (M$)',
                      tools='box_zoom,reset,hover,crosshair',
                      width=1000,
                      plot_height=300,
                      x_range=[0, 1200],
                      y_range=[0, 120])
    earn_fig.title_text_font_size = '15pt'
    earn_fig.xaxis.axis_label_text_font_size = '11pt'
    earn_fig.yaxis.axis_label_text_font_size = '11pt'
    earn_fig.line('t',
                  'earnings',
                  color='blue',
                  source=source,
                  line_width=5,
                  legend='earnings')
    earn_fig.line('t',
                  'expenses',
                  color='red',
                  source=source,
                  line_width=5,
                  legend='expenses')
    earn_fig.legend.orientation = "bottom_right"
    earn_fig.patch([0, 200, 200, 0], [0, 0, 120, 120],
                   color='lightsalmon',
                   alpha=0.35,
                   line_width=0)
    earn_fig.patch([200, 400, 400, 200], [0, 0, 120, 120],
                   color='gold',
                   alpha=0.35,
                   line_width=0)
    earn_fig.patch([400, 1200, 1200, 400], [0, 0, 120, 120],
                   color='darkseagreen',
                   alpha=0.35,
                   line_width=0)
    earn_fig.text([45], [101], ['run-to-fail'])
    earn_fig.text([245], [101], ['scheduled'])
    earn_fig.text([245], [90], ['maintenance'])
    earn_fig.text([445], [101], ['predictive'])
    earn_fig.text([445], [90], ['maintenance'])
    hover = earn_fig.select(dict(type=HoverTool))
    hover.tooltips = [
        ("         Time", "@t"),
        (" earning (M$)", "@earnings"),
        ("expenses (M$)", "@expenses"),
    ]

    #plot revenue vs time
    rev_fig = figure(title='Cumulative Revenue',
                     x_axis_label='Time',
                     y_axis_label='Revenue    (M$)',
                     tools='box_zoom,reset,hover,crosshair',
                     width=1000,
                     plot_height=300,
                     x_range=[0, 1200],
                     y_range=[-15, 10])
    rev_fig.title_text_font_size = '15pt'
    rev_fig.xaxis.axis_label_text_font_size = '11pt'
    rev_fig.yaxis.axis_label_text_font_size = '11pt'
    rev_fig.line('t',
                 'revenue',
                 color='green',
                 source=source,
                 line_width=5,
                 legend='revenue')
    rev_fig.line('t',
                 'zero',
                 color='purple',
                 source=source,
                 line_width=3,
                 alpha=0.5,
                 line_dash=[10, 5])
    rev_fig.legend.orientation = "bottom_right"
    rev_fig.patch([0, 200, 200, 0], [-15, -15, 10, 10],
                  color='lightsalmon',
                  alpha=0.35,
                  line_width=0)
    rev_fig.patch([200, 400, 400, 200], [-15, -15, 10, 10],
                  color='gold',
                  alpha=0.35,
                  line_width=0)
    rev_fig.patch([400, 1200, 1200, 400], [-15, -15, 10, 10],
                  color='darkseagreen',
                  alpha=0.35,
                  line_width=0)
    hover = rev_fig.select(dict(type=HoverTool))
    hover.tooltips = [
        ("         Time", "@t"),
        (" revenue (M$)", "@revenue"),
    ]

    #plot number of motors vs time
    N = events.groupby(['Time', 'state']).count().unstack()['id'].reset_index()
    N.fillna(value=0, inplace=True)
    N['total'] = N.maintenance + N.operating + N.repair
    s1 = ColumnDataSource(data=dict(
        Time=N.Time,
        operating=N.operating,
        maintenance=N.maintenance,
        repair=N.repair,
        total=N.total,
    ))
    motor_fig = figure(title='Number of Motors',
                       x_axis_label='Time',
                       y_axis_label='Number of motors',
                       tools='box_zoom,reset,hover,crosshair',
                       width=1000,
                       plot_height=300,
                       x_range=[0, 1200],
                       y_range=[-10, 210])
    motor_fig.title_text_font_size = '15pt'
    motor_fig.xaxis.axis_label_text_font_size = '11pt'
    motor_fig.yaxis.axis_label_text_font_size = '11pt'
    motor_fig.line('Time',
                   'total',
                   color='blue',
                   source=s1,
                   line_width=3,
                   legend='total')
    motor_fig.line('Time',
                   'operating',
                   color='green',
                   source=s1,
                   line_width=3,
                   legend='operating')
    motor_fig.line('Time',
                   'maintenance',
                   color='orange',
                   source=s1,
                   line_width=3,
                   legend='maintenance')
    motor_fig.line('Time',
                   'repair',
                   color='red',
                   source=s1,
                   line_width=3,
                   legend='repair')
    motor_fig.legend.orientation = "top_right"
    motor_fig.patch([0, 200, 200, 0], [-10, -10, 210, 210],
                    color='lightsalmon',
                    alpha=0.35,
                    line_width=0)
    motor_fig.patch([200, 400, 400, 200], [-10, -10, 210, 210],
                    color='gold',
                    alpha=0.35,
                    line_width=0)
    motor_fig.patch([400, 1200, 1200, 400], [-10, -10, 210, 210],
                    color='darkseagreen',
                    alpha=0.35,
                    line_width=0)

    #display N table
    from bokeh.models.widgets import DataTable, TableColumn
    from bokeh.io import vform
    columns = [
        TableColumn(field='Time', title='Time'),
        TableColumn(field='operating', title='operating'),
        TableColumn(field='maintenance', title='maintenance'),
        TableColumn(field='repair', title='repair'),
        TableColumn(field='total', title='total'),
    ]
    s2 = s1.clone()
    N_table = DataTable(source=s2, columns=columns, width=600, height=300)
    s1.callback = Callback(args=dict(s2=s2),
                           code="""
        var inds = cb_obj.get('selected')['1d'].indices;
        var d1 = cb_obj.get('data');
        var d2 = s2.get('data');
        d2['Time'] = []
        d2['operating'] = []
        d2['maintenance'] = []
        d2['repair'] = []
        d2['total'] = []
        for (i = 0; i < inds.length; i++) {
            d2['Time'].push(d1['Time'][inds[i]])
            d2['operating'].push(d1['operating'][inds[i]])
            d2['maintenance'].push(d1['maintenance'][inds[i]])
            d2['repair'].push(d1['repair'][inds[i]])
            d2['total'].push(d1['total'][inds[i]])
        }
        s2.trigger('change');
    """)

    #export plot to html and return
    plot_grid = vplot(dec_fig, earn_fig, rev_fig, motor_fig, vform(N_table))
    show(plot_grid, new='tab')
    return money, events, N
def plot_3DModel_bokeh(filename, map_data_all_slices, map_depth_all_slices, \
                       color_range_all_slices, profile_data_all, boundary_data, \
                       style_parameter):
    '''
    Plot shear velocity maps and velocity profiles using bokeh

    Input:
        filename is the filename of the resulting html file
        map_data_all_slices contains the velocity model parameters saved for map view plots
        map_depth_all_slices is a list of depths
        color_range_all_slices is a list of color ranges
        profile_data_all constains the velocity model parameters saved for profile plots
        boundary_data is a list of boundaries
        style_parameter contains plotting parameters

    Output:
        None
    
    '''
    xlabel_fontsize = style_parameter['xlabel_fontsize']
    #
    colorbar_data_all_left = []
    colorbar_data_all_right = []
    map_view_ndepth = style_parameter['map_view_ndepth']
    ncolor = len(palette)
    colorbar_top = [0.1 for i in range(ncolor)]
    colorbar_bottom = [0 for i in range(ncolor)]
    map_data_all_slices_depth = []
    for idepth in range(map_view_ndepth): 
        color_min = color_range_all_slices[idepth][0]
        color_max = color_range_all_slices[idepth][1]
        color_step = (color_max - color_min)*1./ncolor
        colorbar_left = np.linspace(color_min,color_max-color_step,ncolor)
        colorbar_right = np.linspace(color_min+color_step,color_max,ncolor)
        colorbar_data_all_left.append(colorbar_left)
        colorbar_data_all_right.append(colorbar_right)
        map_depth = map_depth_all_slices[idepth]
        map_data_all_slices_depth.append('Depth: {0:8.0f} km'.format(map_depth))
    #
    palette_r = palette[::-1]
    # data for the colorbar
    colorbar_data_one_slice = {}
    colorbar_data_one_slice['colorbar_left'] = colorbar_data_all_left[style_parameter['map_view_default_index']]
    colorbar_data_one_slice['colorbar_right'] = colorbar_data_all_right[style_parameter['map_view_default_index']]
    colorbar_data_one_slice_bokeh = ColumnDataSource(data=dict(colorbar_top=colorbar_top,colorbar_bottom=colorbar_bottom,\
                                                               colorbar_left=colorbar_data_one_slice['colorbar_left'],\
                                                               colorbar_right=colorbar_data_one_slice['colorbar_right'],\
                                                               palette_r=palette_r))
    colorbar_data_all_slices_bokeh = ColumnDataSource(data=dict(colorbar_data_all_left=colorbar_data_all_left,\
                                                                colorbar_data_all_right=colorbar_data_all_right))
    #
    map_view_label_lon = style_parameter['map_view_depth_label_lon']
    map_view_label_lat = style_parameter['map_view_depth_label_lat']
    map_data_one_slice_depth = map_data_all_slices_depth[style_parameter['map_view_default_index']]
    map_data_one_slice_depth_bokeh = ColumnDataSource(data=dict(lat=[map_view_label_lat], lon=[map_view_label_lon],
                                                           map_depth=[map_data_one_slice_depth]))
    
    #
    map_view_default_index = style_parameter['map_view_default_index']
    map_data_one_slice = map_data_all_slices[map_view_default_index]

    map_data_one_slice_bokeh = ColumnDataSource(data=dict(x=[style_parameter['map_view_image_lon_min']],\
                   y=[style_parameter['map_view_image_lat_min']],dw=[style_parameter['nlon']*style_parameter['dlon']],\
                   dh=[style_parameter['nlat']*style_parameter['dlat']],map_data_one_slice=[map_data_one_slice]))
    map_data_all_slices_bokeh = ColumnDataSource(data=dict(map_data_all_slices=map_data_all_slices,\
                                                           map_data_all_slices_depth=map_data_all_slices_depth))
    # ------------------------------
    nprofile = len(profile_data_all)
    grid_lat_list = []
    grid_lon_list = []
    width_list = []
    height_list = []
    for iprofile in range(nprofile):
        aprofile = profile_data_all[iprofile]
        grid_lat_list.append(aprofile['lat'])
        grid_lon_list.append(aprofile['lon'])
        width_list.append(style_parameter['map_view_grid_width'])
        height_list.append(style_parameter['map_view_grid_height'])
    grid_data_bokeh = ColumnDataSource(data=dict(lon=grid_lon_list,lat=grid_lat_list,\
                                            width=width_list, height=height_list))
    profile_default_index = style_parameter['profile_default_index']
    selected_dot_on_map_bokeh = ColumnDataSource(data=dict(lat=[grid_lat_list[profile_default_index]], \
                                                           lon=[grid_lon_list[profile_default_index]], \
                                                           width=[style_parameter['map_view_grid_width']],\
                                                           height=[style_parameter['map_view_grid_height']],\
                                                           index=[profile_default_index]))
    # ------------------------------
    profile_vs_all = []
    profile_depth_all = []
    profile_ndepth = style_parameter['profile_ndepth']
    profile_lat_label_list = []
    profile_lon_label_list = []
    for iprofile in range(nprofile):
        aprofile = profile_data_all[iprofile]
        vs_raw = aprofile['vs']
        top_raw = aprofile['top']
        profile_lat_label_list.append('Lat: {0:12.1f}'.format(aprofile['lat']))
        profile_lon_label_list.append('Lon: {0:12.1f}'.format(aprofile['lon']))
        vs_plot = []
        depth_plot = []
        for idepth in range(profile_ndepth):
            vs_plot.append(vs_raw[idepth])
            depth_plot.append(top_raw[idepth])
            vs_plot.append(vs_raw[idepth])
            depth_plot.append(top_raw[idepth+1])
        profile_vs_all.append(vs_plot)
        profile_depth_all.append(depth_plot)
    profile_data_all_bokeh = ColumnDataSource(data=dict(profile_vs_all=profile_vs_all, \
                                                        profile_depth_all=profile_depth_all))
    selected_profile_data_bokeh = ColumnDataSource(data=dict(vs=profile_vs_all[profile_default_index],\
                                                             depth=profile_depth_all[profile_default_index]))
    selected_profile_lat_label_bokeh = ColumnDataSource(data=\
                                dict(x=[style_parameter['profile_lat_label_x']], y=[style_parameter['profile_lat_label_y']],\
                                    lat_label=[profile_lat_label_list[profile_default_index]]))
    selected_profile_lon_label_bokeh = ColumnDataSource(data=\
                                dict(x=[style_parameter['profile_lon_label_x']], y=[style_parameter['profile_lon_label_y']],\
                                    lon_label=[profile_lon_label_list[profile_default_index]]))
    all_profile_lat_label_bokeh = ColumnDataSource(data=dict(profile_lat_label_list=profile_lat_label_list))
    all_profile_lon_label_bokeh = ColumnDataSource(data=dict(profile_lon_label_list=profile_lon_label_list))
    #
    button_ndepth = style_parameter['button_ndepth']
    button_data_all_vs = []
    button_data_all_vp = []
    button_data_all_rho = []
    button_data_all_top = []
    for iprofile in range(nprofile):
        aprofile = profile_data_all[iprofile]
        button_data_all_vs.append(aprofile['vs'][:button_ndepth])
        button_data_all_vp.append(aprofile['vp'][:button_ndepth])
        button_data_all_rho.append(aprofile['rho'][:button_ndepth])
        button_data_all_top.append(aprofile['top'][:button_ndepth])
    button_data_all_bokeh = ColumnDataSource(data=dict(button_data_all_vs=button_data_all_vs,\
                                                       button_data_all_vp=button_data_all_vp,\
                                                       button_data_all_rho=button_data_all_rho,\
                                                       button_data_all_top=button_data_all_top))
    # ==============================
    map_view = Figure(plot_width=style_parameter['map_view_plot_width'], plot_height=style_parameter['map_view_plot_height'], \
                      tools=style_parameter['map_view_tools'], title=style_parameter['map_view_title'], \
                      y_range=[style_parameter['map_view_figure_lat_min'], style_parameter['map_view_figure_lat_max']],\
                      x_range=[style_parameter['map_view_figure_lon_min'], style_parameter['map_view_figure_lon_max']])
    #
    map_view.image('map_data_one_slice',x='x',\
                   y='y',dw='dw',\
                   dh='dh',palette=palette_r,\
                   source=map_data_one_slice_bokeh, level='image')

    depth_slider_callback = CustomJS(args=dict(map_data_one_slice_bokeh=map_data_one_slice_bokeh,\
                                               map_data_all_slices_bokeh=map_data_all_slices_bokeh,\
                                               colorbar_data_all_slices_bokeh=colorbar_data_all_slices_bokeh,\
                                               colorbar_data_one_slice_bokeh=colorbar_data_one_slice_bokeh,\
                                               map_data_one_slice_depth_bokeh=map_data_one_slice_depth_bokeh), code="""

        var d_index = Math.round(cb_obj.value)
        
        var map_data_all_slices = map_data_all_slices_bokeh.data
        
        map_data_one_slice_bokeh.data['map_data_one_slice'] = [map_data_all_slices['map_data_all_slices'][d_index]]
        map_data_one_slice_bokeh.change.emit()
        
        var color_data_all_slices = colorbar_data_all_slices_bokeh.data
        colorbar_data_one_slice_bokeh.data['colorbar_left'] = color_data_all_slices['colorbar_data_all_left'][d_index]
        colorbar_data_one_slice_bokeh.data['colorbar_right'] = color_data_all_slices['colorbar_data_all_right'][d_index]
        colorbar_data_one_slice_bokeh.change.emit()
        
        map_data_one_slice_depth_bokeh.data['map_depth'] = [map_data_all_slices['map_data_all_slices_depth'][d_index]]
        map_data_one_slice_depth_bokeh.change.emit()
        
    """) 
    depth_slider = Slider(start=0, end=style_parameter['map_view_ndepth']-1, \
                          value=map_view_default_index, step=1, \
                          width=style_parameter['map_view_plot_width'],\
                          title=style_parameter['depth_slider_title'], height=50, \
                          callback=depth_slider_callback)
    # ------------------------------
    # add boundaries to map view
    # country boundaries
    map_view.multi_line(boundary_data['country']['longitude'],\
                        boundary_data['country']['latitude'],color='black',\
                        line_width=2, level='underlay',nonselection_line_alpha=1.0,\
                        nonselection_line_color='black')
    # marine boundaries
    map_view.multi_line(boundary_data['marine']['longitude'],\
                        boundary_data['marine']['latitude'],color='black',\
                        level='underlay',nonselection_line_alpha=1.0,\
                        nonselection_line_color='black')
    # shoreline boundaries
    map_view.multi_line(boundary_data['shoreline']['longitude'],\
                        boundary_data['shoreline']['latitude'],color='black',\
                        line_width=2, level='underlay',nonselection_line_alpha=1.0,\
                        nonselection_line_color='black')
    # state boundaries
    map_view.multi_line(boundary_data['state']['longitude'],\
                        boundary_data['state']['latitude'],color='black',\
                        level='underlay',nonselection_line_alpha=1.0,\
                        nonselection_line_color='black')
    # ------------------------------
    # add depth label
    map_view.rect(style_parameter['map_view_depth_box_lon'], style_parameter['map_view_depth_box_lat'], \
                  width=style_parameter['map_view_depth_box_width'], height=style_parameter['map_view_depth_box_height'], \
                  width_units='screen',height_units='screen', color='#FFFFFF', line_width=1., line_color='black', level='underlay')
    map_view.text('lon', 'lat', 'map_depth', source=map_data_one_slice_depth_bokeh,\
                  text_font_size=style_parameter['annotating_text_font_size'],text_align='left',level='underlay')
    # ------------------------------
    map_view.rect('lon', 'lat', width='width', \
                  width_units='screen', height='height', \
                  height_units='screen', line_color='gray', line_alpha=0.5, \
                  selection_line_color='gray', selection_line_alpha=0.5, selection_fill_color=None,\
                  nonselection_line_color='gray',nonselection_line_alpha=0.5, nonselection_fill_color=None,\
                  source=grid_data_bokeh, color=None, line_width=1, level='glyph')
    map_view.rect('lon', 'lat',width='width', \
                  width_units='screen', height='height', \
                  height_units='screen', line_color='#00ff00', line_alpha=1.0, \
                  source=selected_dot_on_map_bokeh, fill_color=None, line_width=3.,level='glyph')
    # ------------------------------
    grid_data_bokeh.callback = CustomJS(args=dict(selected_dot_on_map_bokeh=selected_dot_on_map_bokeh, \
                                                  grid_data_bokeh=grid_data_bokeh,\
                                                  profile_data_all_bokeh=profile_data_all_bokeh,\
                                                  selected_profile_data_bokeh=selected_profile_data_bokeh,\
                                                  selected_profile_lat_label_bokeh=selected_profile_lat_label_bokeh,\
                                                  selected_profile_lon_label_bokeh=selected_profile_lon_label_bokeh, \
                                                  all_profile_lat_label_bokeh=all_profile_lat_label_bokeh, \
                                                  all_profile_lon_label_bokeh=all_profile_lon_label_bokeh, \
                                                 ), code="""
        
        var inds = Math.round(cb_obj.selected['1d'].indices)
        
        var grid_data = grid_data_bokeh.data
        selected_dot_on_map_bokeh.data['lat'] = [grid_data['lat'][inds]]
        selected_dot_on_map_bokeh.data['lon'] = [grid_data['lon'][inds]]
        selected_dot_on_map_bokeh.data['index'] = [inds]
        selected_dot_on_map_bokeh.change.emit()
        
        var profile_data_all = profile_data_all_bokeh.data
        selected_profile_data_bokeh.data['vs'] = profile_data_all['profile_vs_all'][inds]
        selected_profile_data_bokeh.data['depth'] = profile_data_all['profile_depth_all'][inds]
        selected_profile_data_bokeh.change.emit()
        
        var all_profile_lat_label = all_profile_lat_label_bokeh.data['profile_lat_label_list']
        var all_profile_lon_label = all_profile_lon_label_bokeh.data['profile_lon_label_list']
        selected_profile_lat_label_bokeh.data['lat_label'] = [all_profile_lat_label[inds]]
        selected_profile_lon_label_bokeh.data['lon_label'] = [all_profile_lon_label[inds]]
        selected_profile_lat_label_bokeh.change.emit()
        selected_profile_lon_label_bokeh.change.emit()
    """)
    # ------------------------------
    # change style
    map_view.title.text_font_size = style_parameter['title_font_size']
    map_view.title.align = 'center'
    map_view.title.text_font_style = 'normal'
    map_view.xaxis.axis_label = style_parameter['map_view_xlabel']
    map_view.xaxis.axis_label_text_font_style = 'normal'
    map_view.xaxis.axis_label_text_font_size = xlabel_fontsize
    map_view.xaxis.major_label_text_font_size = xlabel_fontsize
    map_view.yaxis.axis_label = style_parameter['map_view_ylabel']
    map_view.yaxis.axis_label_text_font_style = 'normal'
    map_view.yaxis.axis_label_text_font_size = xlabel_fontsize
    map_view.yaxis.major_label_text_font_size = xlabel_fontsize
    map_view.xgrid.grid_line_color = None
    map_view.ygrid.grid_line_color = None
    map_view.toolbar.logo = None
    map_view.toolbar_location = 'above'
    map_view.toolbar_sticky = False
    # ==============================
    # plot colorbar
    colorbar_fig = Figure(tools=[], y_range=(0,0.1),plot_width=style_parameter['map_view_plot_width'], \
                      plot_height=style_parameter['colorbar_plot_height'],title=style_parameter['colorbar_title'])
    colorbar_fig.toolbar_location=None
    colorbar_fig.quad(top='colorbar_top',bottom='colorbar_bottom',left='colorbar_left',right='colorbar_right',\
                  color='palette_r',source=colorbar_data_one_slice_bokeh)
    colorbar_fig.yaxis[0].ticker=FixedTicker(ticks=[])
    colorbar_fig.xgrid.grid_line_color = None
    colorbar_fig.ygrid.grid_line_color = None
    colorbar_fig.xaxis.axis_label_text_font_size = xlabel_fontsize
    colorbar_fig.xaxis.major_label_text_font_size = xlabel_fontsize
    colorbar_fig.xaxis[0].formatter = PrintfTickFormatter(format="%5.2f")
    colorbar_fig.title.text_font_size = xlabel_fontsize
    colorbar_fig.title.align = 'center'
    colorbar_fig.title.text_font_style = 'normal'
    # ==============================
    profile_xrange = Range1d(start=style_parameter['profile_plot_xmin'], end=style_parameter['profile_plot_xmax'])
    profile_yrange = Range1d(start=style_parameter['profile_plot_ymax'], end=style_parameter['profile_plot_ymin'])
    profile_fig = Figure(plot_width=style_parameter['profile_plot_width'], plot_height=style_parameter['profile_plot_height'],\
                         x_range=profile_xrange, y_range=profile_yrange, tools=style_parameter['profile_tools'],\
                         title=style_parameter['profile_title'])
    profile_fig.line('vs','depth',source=selected_profile_data_bokeh, line_width=2, line_color='black')
    # ------------------------------
    # add lat, lon
    profile_fig.rect([style_parameter['profile_label_box_x']], [style_parameter['profile_label_box_y']],\
                     width=style_parameter['profile_label_box_width'], height=style_parameter['profile_label_box_height'],\
                     width_units='screen', height_units='screen', color='#FFFFFF', line_width=1., line_color='black',\
                     level='underlay')
    profile_fig.text('x','y','lat_label', source=selected_profile_lat_label_bokeh)
    profile_fig.text('x','y','lon_label', source=selected_profile_lon_label_bokeh)
    # ------------------------------
    # change style
    profile_fig.xaxis.axis_label = style_parameter['profile_xlabel']
    profile_fig.xaxis.axis_label_text_font_style = 'normal'
    profile_fig.xaxis.axis_label_text_font_size = xlabel_fontsize
    profile_fig.xaxis.major_label_text_font_size = xlabel_fontsize
    profile_fig.yaxis.axis_label = style_parameter['profile_ylabel']
    profile_fig.yaxis.axis_label_text_font_style = 'normal'
    profile_fig.yaxis.axis_label_text_font_size = xlabel_fontsize
    profile_fig.yaxis.major_label_text_font_size = xlabel_fontsize
    profile_fig.xgrid.grid_line_dash = [4, 2]
    profile_fig.ygrid.grid_line_dash = [4, 2]
    profile_fig.title.text_font_size = style_parameter['title_font_size']
    profile_fig.title.align = 'center'
    profile_fig.title.text_font_style = 'normal'
    profile_fig.toolbar_location = 'above'
    profile_fig.toolbar_sticky = False
    profile_fig.toolbar.logo = None
    # ==============================
    profile_slider_callback = CustomJS(args=dict(selected_dot_on_map_bokeh=selected_dot_on_map_bokeh,\
                                                 grid_data_bokeh=grid_data_bokeh, \
                                                 profile_data_all_bokeh=profile_data_all_bokeh, \
                                                 selected_profile_data_bokeh=selected_profile_data_bokeh,\
                                                 selected_profile_lat_label_bokeh=selected_profile_lat_label_bokeh,\
                                                 selected_profile_lon_label_bokeh=selected_profile_lon_label_bokeh, \
                                                 all_profile_lat_label_bokeh=all_profile_lat_label_bokeh, \
                                                 all_profile_lon_label_bokeh=all_profile_lon_label_bokeh), code="""
        var p_index = Math.round(cb_obj.value)
        
        var grid_data = grid_data_bokeh.data
        selected_dot_on_map_bokeh.data['lat'] = [grid_data['lat'][p_index]]
        selected_dot_on_map_bokeh.data['lon'] = [grid_data['lon'][p_index]]
        selected_dot_on_map_bokeh.data['index'] = [p_index]
        selected_dot_on_map_bokeh.change.emit()
        
        var profile_data_all = profile_data_all_bokeh.data
        selected_profile_data_bokeh.data['vs'] = profile_data_all['profile_vs_all'][p_index]
        selected_profile_data_bokeh.data['depth'] = profile_data_all['profile_depth_all'][p_index]
        selected_profile_data_bokeh.change.emit()
        
        var all_profile_lat_label = all_profile_lat_label_bokeh.data['profile_lat_label_list']
        var all_profile_lon_label = all_profile_lon_label_bokeh.data['profile_lon_label_list']
        selected_profile_lat_label_bokeh.data['lat_label'] = [all_profile_lat_label[p_index]]
        selected_profile_lon_label_bokeh.data['lon_label'] = [all_profile_lon_label[p_index]]
        selected_profile_lat_label_bokeh.change.emit()
        selected_profile_lon_label_bokeh.change.emit()
        
    """)
    profile_slider = Slider(start=0, end=nprofile-1, value=style_parameter['profile_default_index'], \
                           step=1, title=style_parameter['profile_slider_title'], \
                           width=style_parameter['profile_plot_width'], height=50,\
                           callback=profile_slider_callback)
    profile_slider_callback.args['profile_index'] = profile_slider
    # ==============================
    simple_text_button_callback = CustomJS(args=dict(button_data_all_bokeh=button_data_all_bokeh,\
                                                    selected_dot_on_map_bokeh=selected_dot_on_map_bokeh), \
                                           code="""
        var index = selected_dot_on_map_bokeh.data['index']
        
        var button_data_vs = button_data_all_bokeh.data['button_data_all_vs'][index]
        var button_data_vp = button_data_all_bokeh.data['button_data_all_vp'][index]
        var button_data_rho = button_data_all_bokeh.data['button_data_all_rho'][index]
        var button_data_top = button_data_all_bokeh.data['button_data_all_top'][index]
        
        var csvContent = "data:text;charset=utf-8,"
        var i = 0
        var temp = csvContent
        temp += "# Layer Top (km)      Vs(km/s)    Vp(km/s)    Rho(g/cm^3) \\n"
        while(button_data_vp[i]) {
            temp+=button_data_top[i].toPrecision(6) + "    " + button_data_vs[i].toPrecision(4) + "   " + \
                    button_data_vp[i].toPrecision(4) + "   " + button_data_rho[i].toPrecision(4) + "\\n"
            i = i + 1
        }
        var encodedUri = encodeURI(temp)
        link = document.createElement('a');
        link.setAttribute('href', encodedUri);
        link.setAttribute('download', 'vel_model.txt');
        link.click();
        
    """)

    simple_text_button = Button(label=style_parameter['simple_text_button_label'], button_type='default', width=style_parameter['button_width'],\
                                callback=simple_text_button_callback)
    # ------------------------------
    model96_button_callback = CustomJS(args=dict(button_data_all_bokeh=button_data_all_bokeh,\
                                                    selected_dot_on_map_bokeh=selected_dot_on_map_bokeh), \
                                           code="""
        var index = selected_dot_on_map_bokeh.data['index']
        var lat = selected_dot_on_map_bokeh.data['lat']
        var lon = selected_dot_on_map_bokeh.data['lon']
        
        var button_data_vs = button_data_all_bokeh.data['button_data_all_vs'][index]
        var button_data_vp = button_data_all_bokeh.data['button_data_all_vp'][index]
        var button_data_rho = button_data_all_bokeh.data['button_data_all_rho'][index]
        var button_data_top = button_data_all_bokeh.data['button_data_all_top'][index]
        
        var csvContent = "data:text;charset=utf-8,"
        var i = 0
        var temp = csvContent
        temp +=  "MODEL." + index + " \\n"
        temp +=  "ShearVelocityModel Lat: "+ lat +"  Lon: " + lon + "\\n"
        temp +=  "ISOTROPIC \\n"
        temp +=  "KGS \\n"
        temp +=  "SPHERICAL EARTH \\n"
        temp +=  "1-D \\n"
        temp +=  "CONSTANT VELOCITY \\n"
        temp +=  "LINE08 \\n"
        temp +=  "LINE09 \\n"
        temp +=  "LINE10 \\n"
        temp +=  "LINE11 \\n"
        temp +=  "      H(KM)   VP(KM/S)   VS(KM/S) RHO(GM/CC)     QP         QS       ETAP       ETAS      FREFP      FREFS \\n"
        while(button_data_vp[i+1]) {
            var thickness = button_data_top[i+1] - button_data_top[i]
            temp+="      " +thickness.toPrecision(6) + "    " + button_data_vp[i].toPrecision(4) + "      " + button_data_vs[i].toPrecision(4) \
                 + "      " + button_data_rho[i].toPrecision(4) + "     0.00       0.00       0.00       0.00       1.00       1.00" + "\\n"
            i = i + 1
        }
        var encodedUri = encodeURI(temp)
        link = document.createElement('a');
        link.setAttribute('href', encodedUri);
        link.setAttribute('download', 'vel_model96.txt');
        link.click();
    """)
    model96_button = Button(label=style_parameter['model96_button_label'], button_type='default', width=style_parameter['button_width'],\
                                callback=model96_button_callback)
    # ==============================
    # annotating text
    annotating_fig01 = Div(text=style_parameter['annotating_html01'], \
        width=style_parameter['annotation_plot_width'], height=style_parameter['annotation_plot_height'])
    annotating_fig02 = Div(text=style_parameter['annotating_html02'],\
        width=style_parameter['annotation_plot_width'], height=style_parameter['annotation_plot_height'])
    # ==============================
    output_file(filename,title=style_parameter['html_title'], mode=style_parameter['library_source'])
    left_column = Column(depth_slider, map_view, colorbar_fig, annotating_fig01, width=style_parameter['left_column_width'])
    button_pannel = Row(simple_text_button, model96_button)
    right_column = Column(profile_slider, profile_fig, button_pannel, annotating_fig02, width=style_parameter['right_column_width'])
    layout = Row(left_column, right_column)
    save(layout)
Beispiel #7
0
def similarityGraph(si, sy, ey, db, abstractsim):

    #calculate similarity and return necessary info
    #ids = pmids of search, dates = dates of pmids, authors = authors of pmids, pmccites = number of cites, Y is x,y coordinate
    #from dimensionality reduction, topwords = labels of clusters from kmeans/tfidf, kcenters = x,y centers of clusters from kmeans
    #d is dictionary for all data storage
    d = SimilarityCalc(si, sy, ey, db, abstractsim)

    # for testing purposes
    # with open('data.pk','wb') as f:
    #      pickle.dump(d,f)

    #convert authors list of lists to list of strings for display
    authors_str = []
    for auths in d['authors']:
        authors_str.append(", ".join(auths))

    #calcualte a scaled pt size based on citation quantity
    minw = 8
    maxw = 30

    # with open('citespkl.p','wb') as f:
    #     pickle.dump(list(map(int,pmccites)),f)
    ptsizes = getScaledSizes(list(map(int, d['pmccites'])), minw, maxw)

    #create colors based on years published
    colors = getScaledColors(d['dates'])

    #colors = ['blue']*len(ids)
    alphas = [1] * len(d['ids'])
    source = ColumnDataSource(data=dict(x=d['Y'][:, 0],
                                        y=d['Y'][:, 1],
                                        PMID=d['ids'],
                                        titles=d['titles'],
                                        authors=authors_str,
                                        journals=d['journals'],
                                        dates=d['dates'],
                                        alphas=alphas,
                                        pmccites=d['pmccites'],
                                        ptsizes=ptsizes,
                                        colors=colors,
                                        colorsperm=colors))

    ########publication view table from selected on tsne plot
    pubview_data = dict(titles=["Title"],
                        dates=["Date"],
                        journals=["Journal"],
                        authors=["Author"],
                        pmccites=["PMC Citations"],
                        PMID=["pmids"])

    pubview_source = ColumnDataSource(pubview_data)

    pubview_columns = [
        TableColumn(field="titles", title="Article Title", width=400),
        TableColumn(field="authors", title="Authors", width=50),
        TableColumn(field="journals", title="Journal", width=50),
        TableColumn(field="dates", title="Date", width=80),
        TableColumn(field="pmccites", title="PMC Citations", width=80),
        TableColumn(field="PMID", title="PMIDS", width=0),
    ]

    pubview_table = DataTable(source=pubview_source,
                              columns=pubview_columns,
                              width=930,
                              height=400)

    source.callback = CustomJS(args=dict(pubview_table=pubview_table),
                               code="""
        var selecteddata = cb_obj.selected["1d"].indices
        var count = 0
        var s1 = cb_obj.get('data');
        var d2 = pubview_table.get('source').get('data');
        d2.index = []
        d2.authors = []
        d2.titles = []
        d2.journals = []
        d2.dates = []
        d2.pmccites = []
        d2.PMID = []
        for(k = 0; k < selecteddata.length; k++){
            tind = selecteddata[k]
            d2.index.push(count)
            d2.authors.push(s1.authors[tind])
            d2.titles.push(s1.titles[tind])
            d2.journals.push(s1.journals[tind])
            d2.dates.push(s1.dates[tind])
            d2.pmccites.push(parseInt(s1.pmccites[tind]))
            d2.PMID.push(s1.PMID[tind])
            count += 1
        }
        console.log(d2)
        pubview_table.trigger('change');
        """)

    pubview_source.callback = CustomJS(code="""
        var selecteddata = cb_obj.selected["1d"].indices
        var s1 = cb_obj.get('data');
        var url = "https://www.ncbi.nlm.nih.gov/pubmed/"+s1.PMID[selecteddata[0]]
        window.open(url,'_blank');

    """)
    #######END TABLE DISPLAY CODE#####

    #####max-width IS IMPORTANT FOR PROPER WRAPPING OF TEXT
    hover = HoverTool(tooltips="""
            <div>
                <div style="max-width: 400px;">
                    <span style="font-size: 12px; font-weight: bold;">@titles</span>
                </div>
                <div style="max-width: 400px;">
                    <span style="font-size: 12px; color: #966;">@authors</span>
                <div>
                <div style="max-width: 400px;">
                    <span style="font-size: 12px; font-style: italic;">@journals, @dates</span>
                <div style="max-width: 400px;">
                    <span style="font-size: 10px;">PMID</span>
                    <span style="font-size: 10px; color: #696;">@PMID</span>
                </div>
                <div style="max-width: 400px;">
                    <span style="font-size: 10px;">PMC Citations</span>
                    <span style="font-size: 10px; color: #696;">@pmccites</span>
                </div>
            </div>
            """)

    resetCallback = CustomJS(args=dict(source=source),
                             code="""
        var data = source.get('data')
        var titles = data['titles']
        for (i=0; i < titles.length; i++) {
            data.colors[i]=data.colorsperm[i]
            data.alphas[i]= 1
        }
        source.trigger('change')
    """)
    #move function from reset callback to below so stuff updates automatically on textbox change
    textCallback = CustomJS(args=dict(source=source),
                            code="""
        var data = source.get('data')
        var value = cb_obj.get('value')
        var words = value.split(" ")
        for (i=0; i < data.titles.length; i++) {
            data.alphas[i]= 0.3
            data.colors[i]=data.colorsperm[i]
        }
        for (i=0; i < data.titles.length; i++) {
            for(j=0; j < words.length; j++){
                if (data.titles[i].toLowerCase().indexOf(words[j].toLowerCase()) !== -1) {
                    if(j == words.length-1){
                        data.colors[i]='orange'
                        data.alphas[i]= 1
                    }
                }else if(data.authors[i].toLowerCase().indexOf(words[j].toLowerCase()) !== -1){
                    if(j == words.length-1){
                        data.colors[i]='orange'
                        data.alphas[i]= 1
                    }
                }else if(data.journals[i].toLowerCase().indexOf(words[j].toLowerCase()) !== -1){
                    if(j == words.length-1){
                        data.colors[i]='orange'
                        data.alphas[i]= 1
                    }
                }else{
                    break
                }
            }
        }
        source.trigger('change')
    """)

    publistcallback = CustomJS(args=dict(pubview_table=pubview_table),
                               code="""
        var pmids = pubview_table.get('source').get('data').PMID;
        var pmidlist = pmids.join()
        var url = "https://www.ncbi.nlm.nih.gov/pubmed/"+pmidlist
        window.open(url,'_blank');
    """)

    TOOLS = 'pan,lasso_select,wheel_zoom,tap,reset'
    p = figure(plot_width=900,
               plot_height=600,
               title="'" + si + "' tSNE similarity",
               tools=[TOOLS, hover],
               active_scroll='wheel_zoom',
               active_drag="lasso_select")

    p.circle('x',
             'y',
             fill_color='colors',
             fill_alpha='alphas',
             size='ptsizes',
             line_color="#000000",
             line_alpha=0.2,
             source=source)

    #word labeles for plots
    wordsources = []
    for idx in list(range(len(d['topwords']))):
        wordsources.append(
            ColumnDataSource(
                dict(x=d['kcenters'][idx][:, 0],
                     y=d['kcenters'][idx][:, 1],
                     text=d['topwords'][idx])))

    wordglyph = Text(x="x",
                     y="y",
                     text="text",
                     text_color="#000000",
                     text_font_style="bold",
                     text_font_size="14pt")
    #5 is used for initial slider set below
    initialclust = 5
    wordholdsource = ColumnDataSource(
        dict(x=d['kcenters'][initialclust][:, 0],
             y=d['kcenters'][initialclust][:, 1],
             text=d['topwords'][initialclust]))
    p.add_glyph(wordholdsource, wordglyph)

    # source = ColumnDataSource(data=dict(x=x, y=y))
    #
    # plot = Figure(plot_width=400, plot_height=400)
    # plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
    args = {}
    args["wordholdsource"] = wordholdsource
    for idx in list(range(len(d['topwords']))):
        args["wordsource" + str(idx + d['minc'])] = wordsources[idx]

    #had to use eval hack because of limitations on the type of objects that can be passed into the callback, limited by bokeh backend
    slidercallback = CustomJS(args=args,
                              code="""
        var f = cb_obj.value
        var ndata = eval('wordsource' + f.toString()).data;
        wordholdsource.data.x = ndata.x
        wordholdsource.data.y = ndata.y
        wordholdsource.data.text = ndata.text
        wordholdsource.trigger('change');
    """)

    wslider = Slider(start=d['minc'],
                     end=d['maxc'],
                     value=d['minc'] + initialclust,
                     step=1,
                     title="# of labels")
    # slider = Slider(start=0.1, end=4, value=1, step=.1, title="power", callback=callback)
    wslider.js_on_change('value', slidercallback)

    #formatting plot
    p.xaxis.axis_label = "Hover to view publication info, Click to open Pubmed link"
    p.xaxis.major_tick_line_color = None  # turn off x-axis major ticks
    p.xaxis.minor_tick_line_color = None  # turn off x-axis minor ticks
    p.yaxis.major_tick_line_color = None  # turn off y-axis major ticks
    p.yaxis.minor_tick_line_color = None
    p.xaxis.major_label_text_font_size = '0pt'  # turn off x-axis tick labels
    p.yaxis.major_label_text_font_size = '0pt'
    left, right, bottom, top = np.amin(d['Y'][:, 0]) * 1.1, np.amax(
        d['Y'][:, 0]) * 1.1, np.amin(d['Y'][:, 1]) * 1.1, np.amax(
            d['Y'][:, 1]) * 1.1
    p.x_range = Range1d(left, right)
    p.y_range = Range1d(bottom, top)

    #tap tool callback
    url = "https://www.ncbi.nlm.nih.gov/pubmed/@PMID"
    taptool = p.select(type=TapTool)
    taptool.callback = OpenURL(url=url)

    #work input callback
    word_input = TextInput(title="Search for term(s) in graph",
                           placeholder="Enter term to highlight",
                           callback=textCallback)
    reset = Button(label="Clear Highlighting",
                   callback=resetCallback,
                   width=150)

    spdiv = Div(text="&nbsp;", width=100, height=20)

    #add addition message saying data was cutoff in case of vague search terms
    if (len(d['rids']) == d['maxids']):
        cutoff_message = "<br>(Search was truncated to " + str(
            d['maxids']) + " newest articles due to memory constraints)"
    else:
        cutoff_message = ""

    tit1 = Div(text="<h1>" + si +
               " similarity plot</h1><br><h5>Displaying the " +
               str(d['sdfc_len']) + "/" + str(len(d['rids'])) +
               " articles that have data on pubmed" + cutoff_message + "</h5>",
               width=930)

    pubmed_list_button = Button(label="Export selected publications to pubmed",
                                callback=publistcallback)
    lt = layout([[tit1], [word_input], [reset, spdiv, wslider], [p],
                 [pubmed_list_button], [pubview_table]])

    return lt
           title="Testing",webgl=True)
p_voc = figure(tools=Tools_voc,
           title="Testing",webgl=True,x_range = p_song.x_range,y_range = p_song.y_range)
p_song.circle('x', 'y', size='size',fill_alpha = 'alpha',fill_color='color',line_color=None, source=source_song)
p_voc.circle('x', 'y', size='size',fill_alpha = 'alpha',fill_color='color',line_color=None, source=source_voc)

source_song.callback = CustomJS(args=dict(source=source_voc), code="""
        var inds = cb_obj.get('selected')['1d'].indices;
        var data = source.get('data');
        size = data['size'];
        sorv = data['SorV'];
        var selection = []
        for (i=0;i<size.length;i++){
            selection.push(0)
        }
        for (i=0;i<inds.length;i++){
            selection[inds[i]]=1;
        }
        for (i=0;i<size.length;i++){
            if(selection[i]==0&sorv[i]==1){
                size[i]=0;
            }
        }
        source.trigger('change');
    """)

callback_alpha = CustomJS(args=dict(source_song=source_song,source_voc=source_voc), code="""
        var song_data = source_song.get('data');
        var voc_data = source_voc.get('data');
        var f = cb_obj.get('value');
        song_alpha = song_data['alpha'];
def selection_plot(response):
    # Let's move these into a settings file somewhere?
    # height/width could potentially be driven by the request?


    # Include color data in the ColumnDataSource to allow for changing the color on
    # the client side.
    urls = [x[0] for x in response["pages"]]
    xdata = [x[1] for x in response["pages"]]
    ydata = [x[2] for x in response["pages"]]
    tags = [x[3] for x in response["pages"]]
    color = []
    custom_tags = ["Custom tags"]
    
    for tag in tags:
        custom = False
        if tag:
            for t in tag:
                if t not in ["Relevant", "Irrelevant", ""]:
                    custom = True
                    if t not in custom_tags:
                        custom_tags.append(t)
            if not custom:    
                color.append(colormap(tag[0]))
            else:
                color.append(colormap("Custom"))
        else:
            color.append(colormap(None))

    source = ColumnDataSource(
        data=dict(
            x=xdata,
            y=ydata,
            urls=urls,
            tags=tags,
            color=color,
        )
    )
    # Callback code for CDS.
    source.callback = CustomJS(code="""
        var inds = cb_obj.get('selected')["1d"].indices;
        var data = cb_obj.get('data');
        BokehPlots.showPages(inds);
    """)


    # Create the figure with FIGURE_WIDTH and FIGURE_HEIGHT
    p = figure(
        tools="hover,wheel_zoom,reset",
        width=FIGURE_WIDTH,
        responsive=True,
        tags=["clusterPlot"],
    )

    # Ensure that the lasso only selects with mouseup, not mousemove.
    p.add_tools(
        LassoSelectTool(select_every_mousemove=False),
    )

    # These turn off the x/y axis ticks
    p.axis.visible = None

    # These turn the major grid off
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None

    # Plot non-selected circles with a particular style using CIRCLE_SIZE and
    # 'color' list
    p.circle("x", "y", size=13, line_width=2, line_alpha=1,
            line_color=None, fill_alpha=1, color='color', source=source,
            name="urls")
    nonselected_circle = Circle(fill_alpha=0.1, line_alpha=0.1, fill_color='color',
            line_color='color')
    renderer = p.select(name="urls")
    renderer.nonselection_glyph = nonselected_circle


    # Create buttons and their callbacks, use button_code string for callbacks.
    button_code = """
        event.preventDefault();
        var inds = source.get('selected')["1d"].indices;
        var data = source.get('data');
        var selected = [];
        tag = "%s";
        for(var i = 0; i < inds.length; i++){
            selected.push({
                x: data.x[inds[i]],
                y: data.y[inds[i]],
                url: data.urls[inds[i]],
                tags: data.tags[inds[i]],
                selected: true,
                possible: false,
            });
            data["color"][inds[i]] = "%s";
        }
        BokehPlots.updateTags(selected, tag, "Apply");
        source.trigger("change");
    """

    textinput_code = """
        event.preventDefault();
        var inds = source.get('selected')["1d"].indices;
        var data = source.get('data');
        var selected = [];
        var tag = cb_obj.get("value");

        // Reinitialise to the default value
        cb_obj.set("value", "Add custom tag...")

        if(tag.indexOf("Add custom tag...") < 0) {
        //Update the custom tags selection list 
        var options = custom_tags_select.get("options");
        if(options.indexOf(tag) < 0){
            options.push(tag);
            custom_tags_select.set("options", options);
        }

        for(var i = 0; i < inds.length; i++){
            selected.push({
                x: data.x[inds[i]],
                y: data.y[inds[i]],
                url: data.urls[inds[i]],
                tags: data.tags[inds[i]],
                selected: true,
                possible: false,
            });
            data["color"][inds[i]] = "%s";
        }
        BokehPlots.updateTags(selected, tag, "Apply");
        source.trigger("change");
        }
    """

    selectinput_code = """
    event.preventDefault();
    var inds = source.get('selected')["1d"].indices;
    var data = source.get('data');
    var selected = [];
    var tag = cb_obj.get("value");    

    cb_obj.set("value", "Enter tags...")
    if(tag.indexOf("Add custom tag...") < 0) {
    for(var i = 0; i < inds.length; i++){
         selected.push({
            x: data.x[inds[i]],
            y: data.y[inds[i]],
            url: data.urls[inds[i]],
            tags: data.tags[inds[i]],
            selected: true,
            possible: false,
         });
         data["color"][inds[i]] = "%s";
    }
    BokehPlots.updateTags(selected, tag, "Apply");
    source.trigger("change");
    }
    """

    # Create buttons and their callbacks, use button_code string for callbacks.
    crawl_code = """
        event.preventDefault();
        var inds = source.get('selected')["1d"].indices;
        var data = source.get('data');
        var selected = [];
        var crawl = '%s';
        for(var i = 0; i < inds.length; i++){
            selected.push(data.urls[inds[i]]);
        }
        BokehPlots.crawlPages(selected, crawl);
        source.trigger("change");
    """

    # Supply color with print formatting.
    but_relevant = Button(label="Relevant", type="success")
    but_relevant.callback = CustomJS(args=dict(source=source),
                    code=button_code % ("Relevant", POSITIVE_COLOR))

    but_irrelevant = Button(label="Irrelevant", type="success")
    but_irrelevant.callback = CustomJS(args=dict(source=source),
                    code=button_code % ("Irrelevant", NEGATIVE_COLOR))

    but_neutral = Button(label="Neutral", type="success")
    but_neutral.callback = CustomJS(args=dict(source=source),
                    code=button_code % ("Neutral", NEUTRAL_COLOR))

    custom_tag_input = TextInput(value="Add custom tag...")
    custom_tag_input.callback = CustomJS(args=dict(source=source),
                    code=textinput_code % (CUSTOM_COLOR))
    
    custom_tag_select = Select(value="Custom tags", options=custom_tags)
    custom_tag_select.callback = CustomJS(args=dict(source=source),
                    code=selectinput_code % (CUSTOM_COLOR))
    custom_tag_input.callback.args["custom_tags_select"] = custom_tag_select

    but_backward_crawl = Button(label="Backlinks", type="success")
    but_backward_crawl.callback = CustomJS(args=dict(source=source),
                                           code=crawl_code % ("backward"))

    but_forward_crawl = Button(label="Forwardlinks", type="success")
    but_forward_crawl.callback = CustomJS(args=dict(source=source),
                                          code=crawl_code % ("forward"))

    
    # Adjust what attributes are displayed by the HoverTool
    hover = p.select(dict(type=HoverTool))
    hover.tooltips = [
        ("urls", "@urls"),
    ]
    tags = hplot(custom_tag_input, custom_tag_select,  but_neutral, but_relevant, but_irrelevant)
    tags_crawl = hplot(but_backward_crawl, but_forward_crawl)
    layout = vplot(p, tags, tags_crawl)
    
    # Combine script and div into a single string.
    plot_code = components(layout)
    return plot_code[0] + plot_code[1]
def make_dashboard(motors, xy_train, operating_earnings, maintenance_cost, repair_cost, run_interval):

    #calculate revenue vs time dataframe 
    print '...generating dashboard...'
    events = get_events(motors)
    events['earnings'] = 0.0
    events.loc[events.state == 'operating', 'earnings'] = operating_earnings
    events['expenses'] = 0.0
    events.loc[events.state == 'maintenance', 'expenses'] = maintenance_cost
    events.loc[events.state == 'repair', 'expenses'] = repair_cost
    money = events.groupby('Time').sum()[['earnings', 'expenses']]
    money['revenue'] = money.earnings - money.expenses
    money['cumulative_earnings'] = money.earnings.cumsum()
    money['cumulative_expenses'] = money.expenses.cumsum()
    money['cumulative_revenue'] = money.revenue.cumsum()
    #map the (P,T) decision surface
    T_min = 50
    T_max = 150
    P_min = 0
    P_max = 100
    T_axis = np.arange(T_min, T_max, 0.5)
    P_axis = np.arange(P_min, P_max, 0.5)
    x, y = np.meshgrid(T_axis, P_axis)
    ttf = np.zeros((len(P_axis), len(T_axis)))
    import copy
    m = copy.deepcopy(motors[0])
    for p_idx in np.arange(len(P_axis)):
        for t_idx in np.arange(len(T_axis)):
            m.Temp = T_axis[t_idx]
            m.Pressure = P_axis[p_idx]
            ttf[p_idx, t_idx] = m.predicted_time_to_fail()

    #plot decision surface
    from bokeh.plotting import figure, show, output_file, ColumnDataSource, vplot
    from bokeh.models import HoverTool, Callback
    from bokeh.io import vform
    output_file('dashboard.html', title='Smart Maintenance Dashboard')
    source = ColumnDataSource(
        data=dict(
            x = xy_train.Temp,
            y = xy_train.Pressure,
            ttf = xy_train.time_to_fail,
            size = 0.6*xy_train.time_to_fail,
        )
    )    
    dec_fig = figure(x_range=[T_min, T_max], y_range=[P_min, P_max], title='SVM Decision Surface',
        x_axis_label='Temperature', y_axis_label='Pressure', tools='box_zoom,reset,hover,crosshair', 
        width=600, plot_height=600)
    dec_fig.title_text_font_size = '18pt'
    dec_fig.xaxis.axis_label_text_font_size = '14pt'
    dec_fig.yaxis.axis_label_text_font_size = '14pt'
    dec_fig.image(image=[-ttf], x=[T_min], y=[P_min], dw=[T_max - T_min], dh=[P_max - P_min], 
        palette='RdYlGn8')
    dec_fig.x('x', 'y', size='size', source=source, fill_alpha=0.5, fill_color='navy', 
        line_color='navy', line_width=1, line_alpha=0.5)
    hover = dec_fig.select(dict(type=HoverTool))
    hover.tooltips = [
        ("Temperature", "@x"),
        ("Pressure", "@y"),
        ("measured lifetime", "@ttf"),
    ]

    #plot earnings vs time
    source = ColumnDataSource(
        data=dict(
            t = money.index,
            earnings = money.cumulative_earnings/1.e6,
            expenses = money.cumulative_expenses/1.e6,
            revenue  = money.cumulative_revenue/1.e6,
            zero = money.cumulative_revenue*0,
        )
    )
    earn_fig = figure(title='Cumulative Earnings & Expenses', x_axis_label='Time', 
        y_axis_label='Earnings & Expenses    (M$)', tools='box_zoom,reset,hover,crosshair', 
        width=1000, plot_height=300, x_range=[0, 1200], y_range=[0, 120])
    earn_fig.title_text_font_size = '15pt'
    earn_fig.xaxis.axis_label_text_font_size = '11pt'
    earn_fig.yaxis.axis_label_text_font_size = '11pt'
    earn_fig.line('t', 'earnings', color='blue', source=source, line_width=5, legend='earnings')
    earn_fig.line('t', 'expenses', color='red', source=source, line_width=5, legend='expenses')
    earn_fig.legend.orientation = "bottom_right"
    earn_fig.patch([0, 200, 200, 0], [0, 0, 120, 120], color='lightsalmon', alpha=0.35, 
        line_width=0)
    earn_fig.patch([200, 400, 400, 200], [0, 0, 120, 120], color='gold', alpha=0.35, 
        line_width=0)
    earn_fig.patch([400, 1200, 1200, 400], [0, 0, 120, 120], color='darkseagreen', 
        alpha=0.35, line_width=0) 
    earn_fig.text([45], [101], ['run-to-fail'])
    earn_fig.text([245], [101], ['scheduled'])
    earn_fig.text([245], [90], ['maintenance'])
    earn_fig.text([445], [101], ['predictive'])
    earn_fig.text([445], [90], ['maintenance'])
    hover = earn_fig.select(dict(type=HoverTool))
    hover.tooltips = [
        ("         Time", "@t"),
        (" earning (M$)", "@earnings"),
        ("expenses (M$)", "@expenses"),
    ]

    #plot revenue vs time
    rev_fig = figure(title='Cumulative Revenue', x_axis_label='Time', 
        y_axis_label='Revenue    (M$)', tools='box_zoom,reset,hover,crosshair', 
        width=1000, plot_height=300, x_range=[0, 1200], y_range=[-15, 10])
    rev_fig.title_text_font_size = '15pt'
    rev_fig.xaxis.axis_label_text_font_size = '11pt'
    rev_fig.yaxis.axis_label_text_font_size = '11pt'
    rev_fig.line('t', 'revenue', color='green', source=source, line_width=5, legend='revenue')
    rev_fig.line('t', 'zero', color='purple', source=source, line_width=3, alpha=0.5, 
        line_dash=[10, 5])
    rev_fig.legend.orientation = "bottom_right"
    rev_fig.patch([0, 200, 200, 0], [-15, -15, 10, 10], color='lightsalmon', alpha=0.35, 
        line_width=0)
    rev_fig.patch([200, 400, 400, 200], [-15, -15, 10, 10], color='gold', alpha=0.35, 
        line_width=0)
    rev_fig.patch([400, 1200, 1200, 400], [-15, -15, 10, 10], color='darkseagreen', 
        alpha=0.35, line_width=0)        
    hover = rev_fig.select(dict(type=HoverTool))
    hover.tooltips = [
        ("         Time", "@t"),
        (" revenue (M$)", "@revenue"),
    ]

    #plot number of motors vs time
    N = events.groupby(['Time', 'state']).count().unstack()['id'].reset_index()
    N.fillna(value=0, inplace=True)
    N['total'] = N.maintenance + N.operating + N.repair
    s1 = ColumnDataSource(
        data=dict(
            Time = N.Time,
            operating = N.operating,
            maintenance = N.maintenance,
            repair = N.repair,
            total = N.total,
        )
    )
    motor_fig = figure(title='Number of Motors', x_axis_label='Time', 
        y_axis_label='Number of motors', tools='box_zoom,reset,hover,crosshair', 
        width=1000, plot_height=300, x_range=[0, 1200], y_range=[-10, 210])
    motor_fig.title_text_font_size = '15pt'
    motor_fig.xaxis.axis_label_text_font_size = '11pt'
    motor_fig.yaxis.axis_label_text_font_size = '11pt'
    motor_fig.line('Time', 'total', color='blue', source=s1, line_width=3, legend='total')
    motor_fig.line('Time', 'operating', color='green', source=s1, line_width=3, legend='operating')
    motor_fig.line('Time', 'maintenance', color='orange', source=s1, line_width=3, legend='maintenance')
    motor_fig.line('Time', 'repair', color='red', source=s1, line_width=3, legend='repair')
    motor_fig.legend.orientation = "top_right"
    motor_fig.patch([0, 200, 200, 0], [-10, -10, 210, 210], color='lightsalmon', alpha=0.35, 
        line_width=0)
    motor_fig.patch([200, 400, 400, 200], [-10, -10, 210, 210], color='gold', alpha=0.35, 
        line_width=0)
    motor_fig.patch([400, 1200, 1200, 400], [-10, -10, 210, 210], color='darkseagreen', 
        alpha=0.35, line_width=0)   

    #display N table
    from bokeh.models.widgets import DataTable, TableColumn
    from bokeh.io import vform
    columns = [
        TableColumn(field='Time', title='Time'),
        TableColumn(field='operating', title='operating'),
        TableColumn(field='maintenance', title='maintenance'),
        TableColumn(field='repair', title='repair'),
        TableColumn(field='total', title='total'),
    ]
    s2 = s1.clone()
    N_table = DataTable(source=s2, columns=columns, width=600, height=300)
    s1.callback = Callback(args=dict(s2=s2), code="""
        var inds = cb_obj.get('selected')['1d'].indices;
        var d1 = cb_obj.get('data');
        var d2 = s2.get('data');
        d2['Time'] = []
        d2['operating'] = []
        d2['maintenance'] = []
        d2['repair'] = []
        d2['total'] = []
        for (i = 0; i < inds.length; i++) {
            d2['Time'].push(d1['Time'][inds[i]])
            d2['operating'].push(d1['operating'][inds[i]])
            d2['maintenance'].push(d1['maintenance'][inds[i]])
            d2['repair'].push(d1['repair'][inds[i]])
            d2['total'].push(d1['total'][inds[i]])
        }
        s2.trigger('change');
    """)

    #export plot to html and return
    plot_grid = vplot(dec_fig, earn_fig, rev_fig, motor_fig, vform(N_table))
    show(plot_grid, new='tab')
    return money, events,N
#First plot
s1 = ColumnDataSource(data=dict(x=x, y=y))
p1 = figure(tools=["lasso_select"], plot_width=600, plot_height=400)
p1.scatter('x', 'y', fill_color='black', line_color=None, size=10, source=s1)

#Second plot
s2 = ColumnDataSource(data=dict(x=[], y=[], y2=[]))
p2 = figure(plot_width=400, plot_height=400, tools=[])

m1 = ColumnDataSource(m1)  #Actual Datasource for the second plot
p2.line(np.arange(0, 100, 1), 'y', source=s2)  # From original data - series 1
p2.line(np.arange(0, 100, 1), 'y2', source=s2)  # From original data - series 2

s1.callback = Callback(args=dict(s2=s2, m1=m1),
                       code="""
  var inds = cb_obj.get('selected')['1d'].indices;
  var d1 = m1.get('data'); 
  var d2 = s2.get('data');
  d2['y'] = []
  d2['y2'] = []
  for (i = 0; i < 11; i++) {o
    d2['y'].push(d1[inds['0']][i]),
    d2['y2'].push(d1[inds['1']][i])
  }
  s2.trigger('change'); 
""")

layout = hplot(p1, p2)
show(layout)
Beispiel #12
0
plot_source2 = ColumnDataSource(data=dict(x=[], y=[]))
p2 = figure(plot_width=500, x_range=(0, 1), y_range=(0, 1))
p2.circle('x', 'y', source=plot_source2)
# scr2, di2 = components(p)

p3 = layouts.column(p, p2)
scr, di = components(p3)

plot_source.callback = CustomJS(args=dict(s2=plot_source2),
                                code="""
    var inds = cb_obj.selected['1d'].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[j]])
    }
    s2.trigger('change');
""")

# plot_source.on_change('selected',flash_selected)

###############################################################


# given tweet index in tweet_list, return the tweet blockquote embed code
def get_tweet_blockquote(tweet_index):
    tweet_id = tweet_list[tweet_index]['id_str']
def selection_plot(response, tag_colors):
    # Let's move these into a settings file somewhere?
    # height/width could potentially be driven by the request?

    # Include color data in the ColumnDataSource to allow for changing the color on
    # the client side.

    urls = [x[0] for x in response["pages"]]
    xdata = [x[1] for x in response["pages"]]
    ydata = [x[2] for x in response["pages"]]
    tags = [x[3] for x in response["pages"]]
    color = []
    custom_tags = ["Custom tags"]

    for tag in tags:
        if tag:
            t = tag[len(tag) - 1]
            if t not in ["Relevant", "Irrelevant", ""]:
                if t not in custom_tags:
                    custom_tags.append(t)
                if ((tag_colors != None) and (t in tag_colors["colors"])):
                    color.append(tag_colors["colors"][t])
                else:
                    color.append(colormap("Custom"))
            else:
                color.append(colormap(t))
        else:
            color.append(colormap(None))

    if tag_colors != None:
        for tag in tag_colors["colors"].keys():
            if tag not in custom_tags:
                custom_tags.append(tag)

    source = ColumnDataSource(data=dict(x=xdata,
                                        y=ydata,
                                        urls=urls,
                                        tags=tags,
                                        color=color,
                                        custom_tags=custom_tags))
    # Callback code for CDS.
    source.callback = CustomJS(code="""
        var inds = cb_obj.get('selected')["1d"].indices;
        var data = cb_obj.get('data');
        BokehPlots.addCustomTags(data['custom_tags']);
        BokehPlots.showPages(inds);
    """)

    # Create the figure with FIGURE_WIDTH and FIGURE_HEIGHT
    p = figure(
        tools="hover,wheel_zoom,reset",
        width=FIGURE_WIDTH,
        height=FIGURE_HEIGHT,
        responsive=True,
        tags=["clusterPlot"],
        min_border_bottom=MIN_BORDER_BOTTOM,
        min_border_top=MIN_BORDER_TOP,
        min_border_left=MIN_BORDER_LEFT,
        min_border_right=MIN_BORDER_RIGHT,
    )

    # Ensure that the lasso only selects with mouseup, not mousemove.
    p.add_tools(LassoSelectTool(select_every_mousemove=False), )

    # These turn off the x/y axis ticks
    p.axis.visible = None

    # These turn the major grid off
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None

    # Plot non-selected circles with a particular style using CIRCLE_SIZE and
    # 'color' list
    p.circle("x",
             "y",
             size=13,
             line_width=2,
             line_alpha=1,
             line_color=None,
             fill_alpha=1,
             color='color',
             source=source,
             name="urls")
    nonselected_circle = Circle(fill_alpha=0.1,
                                line_alpha=0.1,
                                fill_color='color',
                                line_color='color')
    renderer = p.select(name="urls")
    renderer.nonselection_glyph = nonselected_circle

    # Create buttons and their callbacks, use button_code string for callbacks.
    button_code = """
        event.preventDefault();
        var inds = source.get('selected')["1d"].indices;
        var data = source.get('data');
        var selected = [];
        tag = "%s";
        for(var i = 0; i < inds.length; i++){
            selected.push({
                x: data.x[inds[i]],
                y: data.y[inds[i]],
                url: data.urls[inds[i]],
                tags: data.tags[inds[i]],
                color: data.color[inds[i]],
                selected: true,
                possible: false,
            });
        }
        BokehPlots.updateTags(selected, tag, "Apply");
        source.trigger("change");
    """

    textinput_code = """
        event.preventDefault();
        var inds = source.get('selected')["1d"].indices;
        var data = source.get('data');
        var selected = [];
        var tag = cb_obj.get("value");

        // Reinitialise to the default value
        cb_obj.set("value", "Add custom tag...")

        if(tag.indexOf("Add custom tag...") < 0) {
        //Update the custom tags selection list
        var options = custom_tags_select.get("options");
        if(options.indexOf(tag) < 0){
            options.push(tag);
            custom_tags_select.set("options", options);
        }

        for(var i = 0; i < inds.length; i++){
            selected.push({
                x: data.x[inds[i]],
                y: data.y[inds[i]],
                url: data.urls[inds[i]],
                tags: data.tags[inds[i]],
                color: data.color[inds[i]],
                selected: true,
                possible: false,
            });
        }
        BokehPlots.updateTags(selected, tag, "Apply");
        source.trigger("change");
        }
    """

    selectinput_code = """
    event.preventDefault();
    var inds = source.get('selected')["1d"].indices;
    var data = source.get('data');
    var selected = [];
    var tag = cb_obj.get("value");

    cb_obj.set("value", "Enter tags...")
    if(tag.indexOf("Add custom tag...") < 0) {
    for(var i = 0; i < inds.length; i++){
         selected.push({
            x: data.x[inds[i]],
            y: data.y[inds[i]],
            url: data.urls[inds[i]],
            tags: data.tags[inds[i]],
            color: data.color[inds[i]],
            selected: true,
            possible: false,
         });
    }
    BokehPlots.updateTags(selected, tag, "Apply");
    source.trigger("change");
    }
    """

    # Create buttons and their callbacks, use button_code string for callbacks.
    crawl_code = """
        event.preventDefault();
        var inds = source.get('selected')["1d"].indices;
        var data = source.get('data');
        var selected = [];
        var crawl = '%s';
        for(var i = 0; i < inds.length; i++){
            selected.push(data.urls[inds[i]]);
        }
        BokehPlots.crawlPages(selected, crawl);
        source.trigger("change");
    """

    # Supply color with print formatting.
    but_relevant = Button(label="Relevant", type="success")
    but_relevant.callback = CustomJS(args=dict(source=source),
                                     code=button_code % ("Relevant"))

    but_irrelevant = Button(label="Irrelevant", type="success")
    but_irrelevant.callback = CustomJS(args=dict(source=source),
                                       code=button_code % ("Irrelevant"))

    but_neutral = Button(label="Neutral", type="success")
    but_neutral.callback = CustomJS(args=dict(source=source),
                                    code=button_code % ("Neutral"))

    custom_tag_input = TextInput(value="Add custom tag...")
    custom_tag_input.callback = CustomJS(args=dict(source=source),
                                         code=textinput_code % ())

    custom_tag_select = Select(value="Custom tags", options=custom_tags)
    custom_tag_select.callback = CustomJS(args=dict(source=source),
                                          code=selectinput_code % ())
    custom_tag_input.callback.args["custom_tags_select"] = custom_tag_select

    but_backward_crawl = Button(label="Backlinks", type="success")
    but_backward_crawl.callback = CustomJS(args=dict(source=source),
                                           code=crawl_code % ("backward"))

    but_forward_crawl = Button(label="Forwardlinks", type="success")
    but_forward_crawl.callback = CustomJS(args=dict(source=source),
                                          code=crawl_code % ("forward"))

    # Adjust what attributes are displayed by the HoverTool
    hover = p.select(dict(type=HoverTool))
    hover.tooltips = [
        ("urls", "@urls"),
    ]
    tags = hplot(but_neutral,
                 but_relevant,
                 but_irrelevant,
                 custom_tag_input,
                 custom_tag_select,
                 height=40)
    tags_crawl = hplot(but_backward_crawl, but_forward_crawl)
    layout = vplot(p, tags, tags_crawl)

    # Combine script and div into a single string.
    plot_code = components(layout)
    return plot_code[0] + plot_code[1]
def selection_plot(response):
    # Let's move these into a settings file somewhere?
    # height/width could potentially be driven by the request?


    # Include color data in the ColumnDataSource to allow for changing the color on
    # the client side.
    urls = [x[0] for x in response["pages"]]
    xdata = [x[1] for x in response["pages"]]
    ydata = [x[2] for x in response["pages"]]
    tags = [x[3] for x in response["pages"]]
    color = [colormap(x[0]) if x else colormap(None) for x in tags]

    source = ColumnDataSource(
        data=dict(
            x=xdata,
            y=ydata,
            urls=urls,
            tags=tags,
            color=color,
        )
    )
    # Callback code for CDS.
    source.callback = CustomJS(code="""
        var inds = cb_obj.get('selected')["1d"].indices;
        var data = cb_obj.get('data');
        BokehPlots.showPages(inds);
    """)


    # Create the figure with FIGURE_WIDTH and FIGURE_HEIGHT
    p = figure(tools="hover", width=FIGURE_WIDTH,
            toolbar_location=None, responsive=True, tags=["clusterPlot"])

    # Ensure that the lasso only selects with mouseup, not mousemove.
    p.add_tools(LassoSelectTool(select_every_mousemove=False))

    # These turn off the x/y axis ticks
    p.axis.visible = None

    # These turn the major grid off
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None

    # Plot non-selected circles with a particular style using CIRCLE_SIZE and
    # 'color' list
    p.circle("x", "y", size=13, line_width=2, line_alpha=1,
            line_color=None, fill_alpha=1, color='color', source=source,
            name="urls")
    nonselected_circle = Circle(fill_alpha=0.1, line_alpha=0.1, fill_color='color',
            line_color='color')
    renderer = p.select(name="urls")
    renderer.nonselection_glyph = nonselected_circle


    # Create buttons and their callbacks, use button_code string for callbacks.
    button_code = """
        event.preventDefault();
        var inds = source.get('selected')["1d"].indices;
        var data = source.get('data');
        var selected = [];
        tag = "%s";
        for(var i = 0; i < inds.length; i++){
            selected.push({
                x: data.x[inds[i]],
                y: data.y[inds[i]],
                url: data.urls[inds[i]],
                tags: data.tags[inds[i]],
                selected: true,
                possible: false,
            });
            data["color"][inds[i]] = "%s";
        }
        BokehPlots.updateTags(selected, tag, inds);
        source.trigger("change");
    """

    # Supply color with print formatting.
    button1 = Button(label="Relevant", type="success")
    button1.callback = CustomJS(args=dict(source=source),
            code=button_code % ("Relevant", POSITIVE_COLOR))

    button2 = Button(label="Irrelevant", type="success")
    button2.callback = CustomJS(args=dict(source=source),
            code=button_code % ("Irrelevant", NEGATIVE_COLOR))

    button3 = Button(label="Neutral", type="success")
    button3.callback = CustomJS(args=dict(source=source),
            code=button_code % ("Neutral", NEUTRAL_COLOR))


    # Adjust what attributes are displayed by the HoverTool
    hover = p.select(dict(type=HoverTool))
    hover.tooltips = [
        ("urls", "@urls"),
    ]
    layout = vform(p, button1, button2, button3)

    # Combine script and div into a single string.
    plot_code = components(layout)
    return plot_code[0] + plot_code[1]
source_song.callback = CustomJS(
    args=dict(source=source_voc, sf=source_voc_fix, svs=source_voc_size),
    code="""
        var inds = cb_obj.get('selected')['1d'].indices;
        var song_data = cb_obj.get('data');
        var voc_data = source.get('data');
        var voc_size = sf.get('data')['size'][0];
        var voc_alpha = sf.get('data')['alpha'][0];
        var voc_size_tmp = svs.get('data')['size'];
        function sum( obj ) {
            var sum = 0;
            for( var el in obj ) {
                if( obj.hasOwnProperty( el ) ) {
                  sum += parseFloat( obj[el] );
                }
            }
          return sum;
        }
        function normalize(voc){
            var summed = sum(voc);
            //console.log(Object.keys(voc));
            for(var el in voc){
                voc[el] = voc[el]/summed;
            }
            return voc;
        }
        Object.extend = function(destination, source) {
            for (var property in source) {
                if (destination.hasOwnProperty(property)) {
                    destination[property] += source[property];
                }else{
                    destination[property]=source[property];
                }
            }
            return destination;
        };
        var vocs = {

        };
        for (i = 0; i < inds.length; i++) {
            vocs = Object.extend(vocs, song_data['lyrics'][inds[i]]);
            //var key = Object.keys(song_data['lyrics'][inds[i]]);
            //for (j=0;j<key.length;j++){
            //    vocs.add(key[j]);
            //}
        }
        var voc_sum = sum(vocs);
        vocs = normalize(vocs);//do the normalization to all voc
        var key = Object.keys(vocs);
        var select_array = new Array(voc_data['alpha'].length);
        key.forEach(function(value) {
            select_array[value]=1;
        });
        function componentToHex(c) {
            var hex = c.toString(16);
            return hex.length == 1 ? "0" + hex : hex;
        }

        function rgbToHex(r, g, b) {
            return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
        }

        for (i=0;i<select_array.length;i++){
            if(inds.length==0){
                voc_data['alpha'][i] = voc_alpha;
                voc_data['size'][i] = voc_size_tmp[i];//TODO:Change to Document Freq.
                voc_data['color'][i] = rgbToHex(255, 0, 0);
            }else{
                if(select_array[i]==1){
                    voc_data['alpha'][i] = voc_alpha;
                    voc_data['size'][i] = Math.pow(vocs[i]*voc_data['docfreq'][i]*select_array.length/inds.length,voc_size);//TODO:Change to tf-idf with normalized voc tf with normalized by song count
                    //voc_data['size'][i] = Math.pow(vocs[i]*select_array.length/inds.length,voc_size);//TODO:Change to tf
                    //voc_data['size'][i] = Math.pow(vocs[i]*voc_data['docfreq'][i]*voc_sum,voc_size);//TODO:Change to tf-idf with normalized voc tf with normalized by term count
                    //voc_data['size'][i] = Math.pow(vocs[i]*voc_sum,voc_size);//TODO:Change to tf
                    voc_data['color'][i] = rgbToHex(255,voc_data['size'][i],0);//map from size
                    voc_size_tmp[i]=voc_data['size'][i];
                }else{
                    voc_data['alpha'][i] = 0;
                    voc_data['size'][i] = 0;
                    voc_data['color'][i] = rgbToHex(255, 0, 0);
                }
            }

        }

        source.trigger('change');
    """,
)
Beispiel #16
0
def yearGraph(si, sy, ey):
    years = list(range(sy, ey))

    ss = quote(si)
    p = figure(title="Articles containing: " + si,
               plot_width=600,
               plot_height=300,
               x_axis_label="Year",
               y_axis_label="Total Articles")

    ##FOR SEARCHING YOU WILL NEED TO ESCAPE SPACES AND SPECIAL CHARS
    yearcounts, ids = getYears(ss, years)
    pre = time.time()
    titles, dates, authors, journals, pmccites = getPMIDInfo(ids)
    print("Gathered PMID Summary for counts:" + str(time.time() - pre))

    p.line(years, yearcounts, color='blue')

    #Parse out statisitcs about returned data
    authors_str = []
    for auths in authors:
        authors_str.append(", ".join(auths))
    pmidPD = pd.DataFrame(
        data={
            'titles': titles,
            'dates': dates,
            'authors': authors,
            'authors_str': authors_str,
            'journals': journals,
            'pmccites': list(map(int, pmccites))
        })

    #print(pmidPD[:5])
    topPmids = pmidPD.nlargest(10, 'pmccites')
    #####ADD CODE TO DISPLAY TABLE NEXT TO PLOT, determine how good a proxy pmccites is for real number of citation
    #print(topPmids)

    total_authors = Counter(auth for auths in pmidPD['authors']
                            for auth in auths)
    total_authors_norm = Counter()
    for idx, auths in enumerate(pmidPD['authors']):
        for auth in auths:
            total_authors_norm[auth] += pmidPD['pmccites'][idx]

    total_journals = Counter(jour for jour in pmidPD['journals'])

    #get data ready for display in bokeh
    #display nent number of entries
    nent = 100

    topauths = total_authors.most_common(nent)
    topauths_norm = total_authors_norm.most_common(nent)
    topjournals = total_journals.most_common(nent)

    #for displaying authors based on citations and papers
    paper_data = dict(numpapers=[n[1] for n in topauths],
                      auths=[n[0] for n in topauths])
    cite_data = dict(numcites=[n[1] for n in topauths_norm],
                     authscites=[n[0] for n in topauths_norm])
    journal_data = dict(numpapers=[n[1] for n in topjournals],
                        journals=[n[0] for n in topjournals])
    #print(len(titles),len(dates),len(journals),len(authors_str),len(pmccites))
    #print(journals)
    pub_data = dict(titles=titles,
                    dates=dates,
                    journals=journals,
                    authors=authors_str,
                    pmccites=pmccites,
                    PMID=ids)

    pubview_data = dict(titles=["Title"],
                        dates=["Date"],
                        journals=["Journal"],
                        authors=["Author"],
                        pmccites=["PMC Citations"],
                        PMID=["PMID"])
    #publication table that will be populated by

    paper_source = ColumnDataSource(data=paper_data)
    cite_source = ColumnDataSource(data=cite_data)
    journal_source = ColumnDataSource(data=journal_data)

    pub_source = ColumnDataSource(pub_data)
    pubview_source = ColumnDataSource(pubview_data)

    paper_columns = [
        TableColumn(field="numpapers", title="# Papers", width=100),
        TableColumn(field="auths", title="Author", width=150),
    ]
    cite_columns = [
        TableColumn(field="numcites", title="# PMC Citations", width=130),
        TableColumn(field="authscites", title="Author", width=150),
    ]

    journal_columns = [
        TableColumn(field="numpapers", title="# Papers", width=80),
        TableColumn(field="journals", title="Journal", width=220),
    ]

    template = """
    <div style="background:red
        color: white">
    <%= value %>\ninfo</div>
    """

    formatter = HTMLTemplateFormatter(template=template)

    pubview_columns = [
        TableColumn(field="titles", title="Article Title",
                    formatter=formatter),
        TableColumn(field="authors", title="Authors"),
        TableColumn(field="journals", title="Journal"),
        TableColumn(field="dates", title="Date", width=80),
        TableColumn(field="pmccites", title="PMC Citations", width=80),
    ]

    paper_table = DataTable(source=paper_source,
                            columns=paper_columns,
                            width=250,
                            height=210)
    cite_table = DataTable(source=cite_source,
                           columns=cite_columns,
                           width=280,
                           height=210)
    journal_table = DataTable(source=journal_source,
                              columns=journal_columns,
                              width=300,
                              height=210)

    tit0 = Div(text="<h1>General statistics for " + si + "</h1>", width=930)
    tit1 = Div(
        text=
        "<h1>Common Authors and Journals</h1>\n<h5>(Select author(s) or journal(s) to display related publications)</h5>",
        width=930)
    tit2 = Div(
        text=
        "<h1>Related Publications</h1>\n<h5>(click publication to visit pubmed entry)</h5>",
        width=930)

    spacer = figure(plot_width=50,
                    plot_height=210,
                    logo=None,
                    toolbar_location=None,
                    outline_line_color=None)
    spacer2 = figure(plot_width=50,
                     plot_height=210,
                     logo=None,
                     toolbar_location=None,
                     outline_line_color=None)

    #create table updated by clicks in above tables, for viewing related publications

    pubview_table = DataTable(source=pubview_source,
                              columns=pubview_columns,
                              width=930,
                              height=400)

    # callbacks for each of the table selections

    #JScallback for setting up publications table
    #curspot
    paper_source.callback = CustomJS(args=dict(paper_source=paper_source,
                                               pub_source=pub_source,
                                               pubview_table=pubview_table),
                                     code="""
        var authordata = paper_source.selected["1d"].indices
        var author = 'test'
        var count = 0
        var s1 = paper_source.get('data');
        var d1 = pub_source.get('data');
        var d2 = pubview_table.get('source').get('data');
        d2.index = []
        d2.authors = []
        d2.titles = []
        d2.journals = []
        d2.dates = []
        d2.pmccites = []
        d2.PMID = []
        for(j = 0; j < d1.authors.length; j++){
            for(k = 0; k < authordata.length; k++){
                if (d1.authors[j].toLowerCase().indexOf(s1.auths[authordata[k]].toLowerCase()) !== -1) {
                    d2.index.push(count)
                    d2.authors.push(d1.authors[j])
                    d2.titles.push(d1.titles[j])
                    d2.journals.push(d1.journals[j])
                    d2.dates.push(d1.dates[j])
                    d2.pmccites.push(parseInt(d1.pmccites[j]))
                    d2.PMID.push(d1.PMID[j])
                    count += 1
                    break;
                }
            }
        }
        console.log(d2)
        pubview_table.trigger('change');
        """)

    cite_source.callback = CustomJS(args=dict(cite_source=cite_source,
                                              pub_source=pub_source,
                                              pubview_table=pubview_table),
                                    code="""
        var authordata = cite_source.selected["1d"].indices
        var author = 'test'
        var count = 0
        var s1 = cite_source.get('data');
        var d1 = pub_source.get('data');
        var d2 = pubview_table.get('source').get('data');
        d2.index = []
        d2.authors = []
        d2.titles = []
        d2.journals = []
        d2.dates = []
        d2.pmccites = []
        d2.PMID = []
        for(j = 0; j < d1.authors.length; j++){
            for(k = 0; k < authordata.length; k++){
                if (d1.authors[j].toLowerCase().indexOf(s1.authscites[authordata[k]].toLowerCase()) !== -1) {
                    d2.index.push(count)
                    d2.authors.push(d1.authors[j])
                    d2.titles.push(d1.titles[j])
                    d2.journals.push(d1.journals[j])
                    d2.dates.push(d1.dates[j])
                    d2.pmccites.push(parseInt(d1.pmccites[j]))
                    d2.PMID.push(d1.PMID[j])
                    count += 1
                    break;
                }
            }
        }
        console.log(d2)
        pubview_table.trigger('change');
        """)
    journal_source.callback = CustomJS(args=dict(journal_source=journal_source,
                                                 pub_source=pub_source,
                                                 pubview_table=pubview_table),
                                       code="""
        var journaldata = journal_source.selected["1d"].indices
        var author = 'test'
        var count = 0
        var s1 = journal_source.get('data');
        var d1 = pub_source.get('data');
        var d2 = pubview_table.get('source').get('data');
        d2.index = []
        d2.authors = []
        d2.titles = []
        d2.journals = []
        d2.dates = []
        d2.pmccites = []
        d2.PMID = []
        for(j = 0; j < d1.journals.length; j++){
            for(k = 0; k < journaldata.length; k++){
                //checks to make sure journal name exists, seems like certain publications have no journal name in pubmed
                if(d1.journals[j]){
                    if (d1.journals[j].toLowerCase() == s1.journals[journaldata[k]].toLowerCase()) {
                        d2.index.push(count)
                        d2.authors.push(d1.authors[j])
                        d2.titles.push(d1.titles[j])
                        d2.journals.push(d1.journals[j])
                        d2.dates.push(d1.dates[j])
                        d2.pmccites.push(parseInt(d1.pmccites[j]))
                        d2.PMID.push(d1.PMID[j])
                        count += 1
                        break;
                    }
                }
            }
        }
        console.log(d2)
        pubview_table.trigger('change');
        """)

    pubview_source.callback = CustomJS(code="""
        var selecteddata = cb_obj.selected["1d"].indices
        var s1 = cb_obj.get('data');
        var url = "https://www.ncbi.nlm.nih.gov/pubmed/"+s1.PMID[selecteddata[0]]
        window.open(url,'_blank');

    """)
    ###### write callbacks for other two tables as well

    yearslayout = layout(
        [[tit0], [p], [tit1],
         [paper_table, spacer, cite_table, spacer2, journal_table], [tit2],
         [pubview_table]])

    #show(yearslayout)

    #     print(total_authors.most_common(10))
    #     print(total_authors_norm.most_common(10))
    #     print(total_authors['Harley CB'], total_authors['Thomson JA'])

    #show(p)
    return yearslayout
def plot_waveform_bokeh(filename,waveform_list,metadata_list,station_lat_list,\
                       station_lon_list, event_lat, event_lon, boundary_data, style_parameter):
    xlabel_fontsize = style_parameter['xlabel_fontsize']
    #
    map_station_location_bokeh = ColumnDataSource(data=dict(map_lat_list=station_lat_list,\
                                                            map_lon_list=station_lon_list))
    dot_default_index = 0
    selected_dot_on_map_bokeh = ColumnDataSource(data=dict(lat=[station_lat_list[dot_default_index]],\
                                                           lon=[station_lon_list[dot_default_index]],\
                                                           index=[dot_default_index]))
    map_view = Figure(plot_width=style_parameter['map_view_plot_width'], \
                      plot_height=style_parameter['map_view_plot_height'], \
                      y_range=[style_parameter['map_view_lat_min'],\
                    style_parameter['map_view_lat_max']], x_range=[style_parameter['map_view_lon_min'],\
                    style_parameter['map_view_lon_max']], tools=style_parameter['map_view_tools'],\
                    title=style_parameter['map_view_title'])
    # ------------------------------
    # add boundaries to map view
    # country boundaries
    map_view.multi_line(boundary_data['country']['longitude'],\
                        boundary_data['country']['latitude'],color='gray',\
                        line_width=2, level='underlay', nonselection_line_alpha=1.0,\
                        nonselection_line_color='gray')
    # marine boundaries
    map_view.multi_line(boundary_data['marine']['longitude'],\
                        boundary_data['marine']['latitude'],color='gray',\
                        level='underlay', nonselection_line_alpha=1.0,\
                        nonselection_line_color='gray')
    # shoreline boundaries
    map_view.multi_line(boundary_data['shoreline']['longitude'],\
                        boundary_data['shoreline']['latitude'],color='gray',\
                        line_width=2, nonselection_line_alpha=1.0, level='underlay',
                        nonselection_line_color='gray')
    # state boundaries
    map_view.multi_line(boundary_data['state']['longitude'],\
                        boundary_data['state']['latitude'],color='gray',\
                        level='underlay', nonselection_line_alpha=1.0,\
                        nonselection_line_color='gray')
    #
    map_view.triangle('map_lon_list', 'map_lat_list', source=map_station_location_bokeh, \
                      line_color='gray', size=style_parameter['marker_size'], fill_color='black',\
                      selection_color='black', selection_line_color='gray',\
                      selection_fill_alpha=1.0,\
                      nonselection_fill_alpha=1.0, nonselection_fill_color='black',\
                      nonselection_line_color='gray', nonselection_line_alpha=1.0)
    map_view.triangle('lon','lat', source=selected_dot_on_map_bokeh,\
                      size=style_parameter['selected_marker_size'], line_color='black',fill_color='red')
    map_view.asterisk([event_lon], [event_lat], size=style_parameter['event_marker_size'], line_width=3, line_color='red', \
                      fill_color='red')
    # change style
    map_view.title.text_font_size = style_parameter['title_font_size']
    map_view.title.align = 'center'
    map_view.title.text_font_style = 'normal'
    map_view.xaxis.axis_label = style_parameter['map_view_xlabel']
    map_view.xaxis.axis_label_text_font_style = 'normal'
    map_view.xaxis.axis_label_text_font_size = xlabel_fontsize
    map_view.xaxis.major_label_text_font_size = xlabel_fontsize
    map_view.yaxis.axis_label = style_parameter['map_view_ylabel']
    map_view.yaxis.axis_label_text_font_style = 'normal'
    map_view.yaxis.axis_label_text_font_size = xlabel_fontsize
    map_view.yaxis.major_label_text_font_size = xlabel_fontsize
    map_view.xgrid.grid_line_color = None
    map_view.ygrid.grid_line_color = None
    map_view.toolbar.logo = None
    map_view.toolbar_location = 'above'
    map_view.toolbar_sticky = False
    # --------------------------------------------------------
    max_waveform_length = 0
    max_waveform_amp = 0
    ncurve = len(waveform_list)
    for a_sta in waveform_list:
        for a_trace in a_sta:
            if len(a_trace) > max_waveform_length:
                max_waveform_length = len(a_trace)
            if np.max(np.abs(a_trace)) > max_waveform_amp:
                max_waveform_amp = np.max(np.abs(a_trace))
    #
    plotting_list = []
    for a_sta in waveform_list:
        temp = []
        for a_trace in a_sta:
            if len(a_trace) < max_waveform_length:
                a_trace = np.append(a_trace,np.zeros([(max_waveform_length-len(a_trace)),1]))
            temp.append(list(a_trace))
        plotting_list.append(temp)
    #
    time_list = []
    for ista in range(len(plotting_list)):
        a_sta = plotting_list[ista]
        temp = []
        for itr in range(len(a_sta)):
            a_trace = a_sta[itr]
            delta = metadata_list[ista][itr]['delta']
            time = list(np.arange(len(a_trace))*delta)
            temp.append(time)
        #
        time_list.append(temp)
    #
    reftime_label_list = []
    channel_label_list = []
    for ista in range(len(metadata_list)):
        temp_ref = []
        temp_channel = []
        a_sta = metadata_list[ista]
        for a_trace in a_sta:
            temp_ref.append('Starting from '+a_trace['starttime'])
            temp_channel.append(a_trace['network']+'_'+a_trace['station']+'_'+a_trace['channel'])
        reftime_label_list.append(temp_ref)
        channel_label_list.append(temp_channel)
    # --------------------------------------------------------
    curve_fig01 = Figure(plot_width=style_parameter['curve_plot_width'], plot_height=style_parameter['curve_plot_height'], \
                       y_range=(-max_waveform_amp*1.05,max_waveform_amp*1.05), \
                       x_range=(0,max_waveform_length),\
                    tools=['save','box_zoom','ywheel_zoom','xwheel_zoom','reset','crosshair','pan']) 
    #
    curve_index = 0
    select_curve_data = plotting_list[dot_default_index][curve_index]
    select_curve_time = time_list[dot_default_index][curve_index]
    
    selected_curve_data_bokeh01 = ColumnDataSource(data=dict(time=select_curve_time,amp=select_curve_data))
    select_reftime_label = reftime_label_list[dot_default_index][curve_index]
    selected_reftime_label_bokeh01 = ColumnDataSource(data=dict(x=[style_parameter['curve_reftime_label_x']],\
                                                                y=[style_parameter['curve_reftime_label_y']],\
                                                                label=[select_reftime_label]))
    select_channel_label = channel_label_list[dot_default_index][curve_index]
    selected_channel_label_bokeh01 = ColumnDataSource(data=dict(x=[style_parameter['curve_channel_label_x']],\
                                                                y=[style_parameter['curve_channel_label_y']],\
                                                                label=[select_channel_label]))
    all_curve_data_bokeh = ColumnDataSource(data=dict(t=time_list, amp=plotting_list))
    all_reftime_label_bokeh = ColumnDataSource(data=dict(label=reftime_label_list))
    all_channel_label_bokeh = ColumnDataSource(data=dict(label=channel_label_list))
    # plot waveform
    curve_fig01.line('time','amp', source=selected_curve_data_bokeh01,\
                   line_color='black')
    # add refference time as a label
    curve_fig01.text('x', 'y', 'label', source=selected_reftime_label_bokeh01)
    # add channel label
    curve_fig01.text('x', 'y', 'label', source=selected_channel_label_bokeh01)
    # change style
    curve_fig01.title.text_font_size = style_parameter['title_font_size']
    curve_fig01.title.align = 'center'
    curve_fig01.title.text_font_style = 'normal'
    curve_fig01.xaxis.axis_label = style_parameter['curve_xlabel']
    curve_fig01.xaxis.axis_label_text_font_style = 'normal'
    curve_fig01.xaxis.axis_label_text_font_size = xlabel_fontsize
    curve_fig01.xaxis.major_label_text_font_size = xlabel_fontsize
    curve_fig01.yaxis.axis_label = style_parameter['curve_ylabel']
    curve_fig01.yaxis.axis_label_text_font_style = 'normal'
    curve_fig01.yaxis.axis_label_text_font_size = xlabel_fontsize
    curve_fig01.yaxis.major_label_text_font_size = xlabel_fontsize
    curve_fig01.toolbar.logo = None
    curve_fig01.toolbar_location = 'above'
    curve_fig01.toolbar_sticky = False
    # --------------------------------------------------------
    curve_fig02 = Figure(plot_width=style_parameter['curve_plot_width'], plot_height=style_parameter['curve_plot_height'], \
                       y_range=(-max_waveform_amp*1.05,max_waveform_amp*1.05), \
                       x_range=(0,max_waveform_length),\
                    tools=['save','box_zoom','ywheel_zoom','xwheel_zoom','reset','crosshair','pan']) 
    #
    curve_index = 1
    select_curve_data = plotting_list[dot_default_index][curve_index]
    select_curve_time = time_list[dot_default_index][curve_index]
    selected_curve_data_bokeh02 = ColumnDataSource(data=dict(time=select_curve_time,amp=select_curve_data))
    select_channel_label = channel_label_list[dot_default_index][curve_index]
    selected_channel_label_bokeh02 = ColumnDataSource(data=dict(x=[style_parameter['curve_channel_label_x']],\
                                                                y=[style_parameter['curve_channel_label_y']],\
                                                                label=[select_channel_label]))
    # plot waveform
    curve_fig02.line('time','amp', source=selected_curve_data_bokeh02,\
                   line_color='black')
    # add channel label
    curve_fig02.text('x', 'y', 'label', source=selected_channel_label_bokeh02)
    # change style
    curve_fig02.title.text_font_size = style_parameter['title_font_size']
    curve_fig02.title.align = 'center'
    curve_fig02.title.text_font_style = 'normal'
    curve_fig02.xaxis.axis_label = style_parameter['curve_xlabel']
    curve_fig02.xaxis.axis_label_text_font_style = 'normal'
    curve_fig02.xaxis.axis_label_text_font_size = xlabel_fontsize
    curve_fig02.xaxis.major_label_text_font_size = xlabel_fontsize
    curve_fig02.yaxis.axis_label = style_parameter['curve_ylabel']
    curve_fig02.yaxis.axis_label_text_font_style = 'normal'
    curve_fig02.yaxis.axis_label_text_font_size = xlabel_fontsize
    curve_fig02.yaxis.major_label_text_font_size = xlabel_fontsize
    curve_fig02.toolbar.logo = None
    curve_fig02.toolbar_location = 'above'
    curve_fig02.toolbar_sticky = False
    # --------------------------------------------------------
    curve_fig03 = Figure(plot_width=style_parameter['curve_plot_width'], plot_height=style_parameter['curve_plot_height'], \
                       y_range=(-max_waveform_amp*1.05,max_waveform_amp*1.05), \
                       x_range=(0,max_waveform_length),\
                    tools=['save','box_zoom','ywheel_zoom','xwheel_zoom','reset','crosshair','pan']) 
    #
    curve_index = 2
    select_curve_data = plotting_list[dot_default_index][curve_index]
    select_curve_time = time_list[dot_default_index][curve_index]
    selected_curve_data_bokeh03 = ColumnDataSource(data=dict(time=select_curve_time,amp=select_curve_data))
    select_channel_label = channel_label_list[dot_default_index][curve_index]
    selected_channel_label_bokeh03 = ColumnDataSource(data=dict(x=[style_parameter['curve_channel_label_x']],\
                                                                y=[style_parameter['curve_channel_label_y']],\
                                                                label=[select_channel_label]))
    # plot waveform
    curve_fig03.line('time','amp', source=selected_curve_data_bokeh03,\
                   line_color='black')
    # add channel label
    curve_fig03.text('x', 'y', 'label', source=selected_channel_label_bokeh03)
    # change style
    curve_fig03.title.text_font_size = style_parameter['title_font_size']
    curve_fig03.title.align = 'center'
    curve_fig03.title.text_font_style = 'normal'
    curve_fig03.xaxis.axis_label = style_parameter['curve_xlabel']
    curve_fig03.xaxis.axis_label_text_font_style = 'normal'
    curve_fig03.xaxis.axis_label_text_font_size = xlabel_fontsize
    curve_fig03.xaxis.major_label_text_font_size = xlabel_fontsize
    curve_fig03.yaxis.axis_label = style_parameter['curve_ylabel']
    curve_fig03.yaxis.axis_label_text_font_style = 'normal'
    curve_fig03.yaxis.axis_label_text_font_size = xlabel_fontsize
    curve_fig03.yaxis.major_label_text_font_size = xlabel_fontsize
    curve_fig03.toolbar.logo = None
    curve_fig03.toolbar_location = 'above'
    curve_fig03.toolbar_sticky = False
    # --------------------------------------------------------
    map_station_location_bokeh.callback = CustomJS(args=dict(selected_dot_on_map_bokeh=selected_dot_on_map_bokeh,\
                                                            map_station_location_bokeh=map_station_location_bokeh,\
                                                            selected_curve_data_bokeh01=selected_curve_data_bokeh01,\
                                                            selected_curve_data_bokeh02=selected_curve_data_bokeh02,\
                                                            selected_curve_data_bokeh03=selected_curve_data_bokeh03,\
                                                            selected_channel_label_bokeh01=selected_channel_label_bokeh01,\
                                                            selected_channel_label_bokeh02=selected_channel_label_bokeh02,\
                                                            selected_channel_label_bokeh03=selected_channel_label_bokeh03,\
                                                            selected_reftime_label_bokeh01=selected_reftime_label_bokeh01,\
                                                            all_reftime_label_bokeh=all_reftime_label_bokeh,\
                                                            all_channel_label_bokeh=all_channel_label_bokeh,\
                                                            all_curve_data_bokeh=all_curve_data_bokeh), code="""
    var inds = Math.round(cb_obj.selected['1d'].indices)
    
    selected_dot_on_map_bokeh.data['index'] = [inds]
    var new_loc = map_station_location_bokeh.data
    
    selected_dot_on_map_bokeh.data['lat'] = [new_loc['map_lat_list'][inds]]
    selected_dot_on_map_bokeh.data['lon'] = [new_loc['map_lon_list'][inds]]
    
    selected_dot_on_map_bokeh.change.emit()
    
    selected_curve_data_bokeh01.data['t'] = all_curve_data_bokeh.data['t'][inds][0]
    selected_curve_data_bokeh01.data['amp'] = all_curve_data_bokeh.data['amp'][inds][0]

    selected_curve_data_bokeh01.change.emit()
    
    selected_curve_data_bokeh02.data['t'] = all_curve_data_bokeh.data['t'][inds][1]
    selected_curve_data_bokeh02.data['amp'] = all_curve_data_bokeh.data['amp'][inds][1]

    selected_curve_data_bokeh02.change.emit()
    
    selected_curve_data_bokeh03.data['t'] = all_curve_data_bokeh.data['t'][inds][2]
    selected_curve_data_bokeh03.data['amp'] = all_curve_data_bokeh.data['amp'][inds][2]

    selected_curve_data_bokeh03.change.emit()
    
    selected_reftime_label_bokeh01.data['label'] = [all_reftime_label_bokeh.data['label'][inds][0]]
    
    selected_reftime_label_bokeh01.change.emit()
    
    selected_channel_label_bokeh01.data['label'] = [all_channel_label_bokeh.data['label'][inds][0]]
    
    selected_channel_label_bokeh01.change.emit()
    
    selected_channel_label_bokeh02.data['label'] = [all_channel_label_bokeh.data['label'][inds][1]]
    
    selected_channel_label_bokeh02.change.emit()
    
    selected_channel_label_bokeh03.data['label'] = [all_channel_label_bokeh.data['label'][inds][2]]
    
    selected_channel_label_bokeh03.change.emit()
    """)
    curve_slider_callback = CustomJS(args=dict(selected_dot_on_map_bokeh=selected_dot_on_map_bokeh,\
                                                map_station_location_bokeh=map_station_location_bokeh,\
                                                selected_curve_data_bokeh01=selected_curve_data_bokeh01,\
                                                selected_curve_data_bokeh02=selected_curve_data_bokeh02,\
                                                selected_curve_data_bokeh03=selected_curve_data_bokeh03,\
                                                selected_channel_label_bokeh01=selected_channel_label_bokeh01,\
                                                selected_channel_label_bokeh02=selected_channel_label_bokeh02,\
                                                selected_channel_label_bokeh03=selected_channel_label_bokeh03,\
                                                selected_reftime_label_bokeh01=selected_reftime_label_bokeh01,\
                                                all_reftime_label_bokeh=all_reftime_label_bokeh,\
                                                all_channel_label_bokeh=all_channel_label_bokeh,\
                                                all_curve_data_bokeh=all_curve_data_bokeh),code="""
    var inds = Math.round(cb_obj.value)
    
    selected_dot_on_map_bokeh.data['index'] = [inds]
    var new_loc = map_station_location_bokeh.data
    
    selected_dot_on_map_bokeh.data['lat'] = [new_loc['map_lat_list'][inds]]
    selected_dot_on_map_bokeh.data['lon'] = [new_loc['map_lon_list'][inds]]
    
    selected_dot_on_map_bokeh.change.emit()
    
    selected_curve_data_bokeh01.data['t'] = all_curve_data_bokeh.data['t'][inds][0]
    selected_curve_data_bokeh01.data['amp'] = all_curve_data_bokeh.data['amp'][inds][0]

    selected_curve_data_bokeh01.change.emit()
    
    selected_curve_data_bokeh02.data['t'] = all_curve_data_bokeh.data['t'][inds][1]
    selected_curve_data_bokeh02.data['amp'] = all_curve_data_bokeh.data['amp'][inds][1]

    selected_curve_data_bokeh02.change.emit()
    
    selected_curve_data_bokeh03.data['t'] = all_curve_data_bokeh.data['t'][inds][2]
    selected_curve_data_bokeh03.data['amp'] = all_curve_data_bokeh.data['amp'][inds][2]

    selected_curve_data_bokeh03.change.emit()
    
    selected_reftime_label_bokeh01.data['label'] = [all_reftime_label_bokeh.data['label'][inds][0]]
    
    selected_reftime_label_bokeh01.change.emit()
    
    selected_channel_label_bokeh01.data['label'] = [all_channel_label_bokeh.data['label'][inds][0]]
    
    selected_channel_label_bokeh01.change.emit()
    
    selected_channel_label_bokeh02.data['label'] = [all_channel_label_bokeh.data['label'][inds][1]]
    
    selected_channel_label_bokeh02.change.emit()
    
    selected_channel_label_bokeh03.data['label'] = [all_channel_label_bokeh.data['label'][inds][2]]
    
    selected_channel_label_bokeh03.change.emit()
    """)
    curve_slider = Slider(start=0, end=ncurve-1, value=style_parameter['curve_default_index'], \
                          step=1, title=style_parameter['curve_slider_title'], width=style_parameter['map_view_plot_width'],\
                          height=50, callback=curve_slider_callback)
    
    # ==============================
    # annotating text
    annotating_fig01 = Div(text=style_parameter['annotating_html01'], \
        width=style_parameter['annotation_plot_width'], height=style_parameter['annotation_plot_height'])
    annotating_fig02 = Div(text=style_parameter['annotating_html02'],\
        width=style_parameter['annotation_plot_width'], height=style_parameter['annotation_plot_height'])
    # ==============================
    output_file(filename,title=style_parameter['html_title'],mode=style_parameter['library_source'])
    #
    left_fig = Column(curve_slider, map_view, annotating_fig01, width=style_parameter['left_column_width'] )
    
    right_fig = Column(curve_fig01, curve_fig02, curve_fig03, annotating_fig02, width=style_parameter['right_column_width'])
    layout = Row(left_fig, right_fig)
    save(layout)
def plot_dispersion_bokeh(filename, period_array, curve_data_array, boundary_data, style_parameter):
    '''
    Plot dispersion maps and curves using bokeh
    
    Input:
        filename is the filename of the resulting html file
        period_array is a list of period
        curve_data_array is a list of dispersion curves
        boundary_data is a list of boundaries
        style_parameter contains plotting parameters 
    
    Output:
        None
        
    '''
    xlabel_fontsize = style_parameter['xlabel_fontsize']
    # ==============================
    # prepare data
    map_data_all_slices_velocity = []
    map_data_all_slices_period = []
    map_data_all_slices_color = []
    colorbar_data_all_left = []
    colorbar_data_all_right = []
    nperiod = len(period_array)
    ncurve = len(curve_data_array)
    ncolor = len(palette)
    palette_r = palette[::-1]
    colorbar_top = [0.1 for i in range(ncolor)]
    colorbar_bottom = [0 for i in range(ncolor)]
    for iperiod in range(nperiod):
        one_slice_lat_list = []
        one_slice_lon_list = []
        one_slice_vel_list = []
        
        map_period = period_array[iperiod]
        for icurve in range(ncurve):
            acurve = curve_data_array[icurve]
            curve_lat = acurve['latitude']
            curve_lon = acurve['longitude']
            curve_vel = acurve['velocity']
            curve_period = acurve['period']
            one_slice_lat_list.append(curve_lat)
            one_slice_lon_list.append(curve_lon)
            if map_period in curve_period:
                curve_period_index = curve_period.index(map_period)
                one_slice_vel_list.append(curve_vel[curve_period_index])
            else:
                one_slice_vel_list.append(style_parameter['nan_value'])
        # get color for dispersion values
        one_slice_vel_mean = np.nanmean(one_slice_vel_list)
        one_slice_vel_std = np.nanstd(one_slice_vel_list)
        
        color_min = one_slice_vel_mean - one_slice_vel_std * style_parameter['spread_factor']
        color_max = one_slice_vel_mean + one_slice_vel_std * style_parameter['spread_factor']
        color_step = (color_max - color_min)*1./ncolor
        one_slice_color_list = get_color_list(one_slice_vel_list,color_min,color_max,palette_r,\
                                             style_parameter['nan_value'],style_parameter['nan_color'])
        colorbar_left = np.linspace(color_min,color_max-color_step,ncolor)
        colorbar_right = np.linspace(color_min+color_step,color_max,ncolor)
        if one_slice_lat_list:
            map_data_all_slices_velocity.append(one_slice_vel_list)
            map_data_all_slices_period.append('Period: {0:6.1f} s'.format(map_period))
            map_data_all_slices_color.append(one_slice_color_list)
            colorbar_data_all_left.append(colorbar_left)
            colorbar_data_all_right.append(colorbar_right)
    # get location for all points
    map_lat_list, map_lon_list = [], []
    map_lat_label_list, map_lon_label_list = [], []
    for i in range(ncurve):
        acurve = curve_data_array[i]
        map_lat_list.append(acurve['latitude'])
        map_lon_list.append(acurve['longitude'])
        map_lat_label_list.append('Lat: {0:12.3f}'.format(acurve['latitude']))
        map_lon_label_list.append('Lon: {0:12.3f}'.format(acurve['longitude']))
    # data for the map view plot
    map_view_label_lon = style_parameter['map_view_period_label_lon']
    map_view_label_lat = style_parameter['map_view_period_label_lat']

    map_data_one_slice = map_data_all_slices_color[style_parameter['map_view_default_index']]
    map_data_one_slice_period = map_data_all_slices_period[style_parameter['map_view_default_index']]
    map_data_one_slice_bokeh = ColumnDataSource(data=dict(map_lat_list=map_lat_list,\
                                                          map_lon_list=map_lon_list,\
                                                          map_data_one_slice=map_data_one_slice))
    map_data_one_slice_period_bokeh = ColumnDataSource(data=dict(lat=[map_view_label_lat], lon=[map_view_label_lon],
                                                       map_period=[map_data_one_slice_period]))
    map_data_all_slices_bokeh = ColumnDataSource(data=dict(map_data_all_slices_color=map_data_all_slices_color,\
                                                          map_data_all_slices_period=map_data_all_slices_period))

    # data for the colorbar
    colorbar_data_one_slice = {}
    colorbar_data_one_slice['colorbar_left'] = colorbar_data_all_left[style_parameter['map_view_default_index']]
    colorbar_data_one_slice['colorbar_right'] = colorbar_data_all_right[style_parameter['map_view_default_index']]
    colorbar_data_one_slice_bokeh = ColumnDataSource(data=dict(colorbar_top=colorbar_top,colorbar_bottom=colorbar_bottom,
                                                               colorbar_left=colorbar_data_one_slice['colorbar_left'],\
                                                               colorbar_right=colorbar_data_one_slice['colorbar_right'],\
                                                               palette_r=palette_r))
    colorbar_data_all_slices_bokeh = ColumnDataSource(data=dict(colorbar_data_all_left=colorbar_data_all_left,\
                                                                colorbar_data_all_right=colorbar_data_all_right))
    # data for dispersion curves
    curve_default_index = style_parameter['curve_default_index']
    selected_dot_on_map_bokeh = ColumnDataSource(data=dict(lat=[map_lat_list[curve_default_index]],\
                                                     lon=[map_lon_list[curve_default_index]],\
                                                     color=[map_data_one_slice[curve_default_index]],\
                                                     index=[curve_default_index]))
    selected_curve_data = curve_data_array[curve_default_index]
    selected_curve_data_bokeh = ColumnDataSource(data=dict(curve_period=selected_curve_data['period'],\
                                                          curve_velocity=selected_curve_data['velocity']))

    period_all = []
    velocity_all = []
    for acurve in curve_data_array:
        period_all.append(acurve['period'])
        velocity_all.append(acurve['velocity'])
    curve_data_all_bokeh = ColumnDataSource(data=dict(period_all=period_all, velocity_all=velocity_all))
    
    selected_curve_lat_label_bokeh = ColumnDataSource(data=dict(x=[style_parameter['curve_lat_label_x']], \
                                                                y=[style_parameter['curve_lat_label_y']],\
                                                                lat_label=[map_lat_label_list[curve_default_index]]))
    selected_curve_lon_label_bokeh = ColumnDataSource(data=dict(x=[style_parameter['curve_lon_label_x']], \
                                                                y=[style_parameter['curve_lon_label_y']],\
                                                                lon_label=[map_lon_label_list[curve_default_index]]))
    all_curve_lat_label_bokeh = ColumnDataSource(data=dict(map_lat_label_list=map_lat_label_list))
    all_curve_lon_label_bokeh = ColumnDataSource(data=dict(map_lon_label_list=map_lon_label_list))
    # ==============================
    map_view = Figure(plot_width=style_parameter['map_view_plot_width'], \
                      plot_height=style_parameter['map_view_plot_height'], \
                      y_range=[style_parameter['map_view_lat_min'],\
                    style_parameter['map_view_lat_max']], x_range=[style_parameter['map_view_lon_min'],\
                    style_parameter['map_view_lon_max']], tools=style_parameter['map_view_tools'],\
                    title=style_parameter['map_view_title'])
    # ------------------------------
    # add boundaries to map view
    # country boundaries
    map_view.multi_line(boundary_data['country']['longitude'],\
                        boundary_data['country']['latitude'],color='black',\
                        line_width=2, level='underlay',nonselection_line_alpha=1.0,\
                        nonselection_line_color='black')
    # marine boundaries
    map_view.multi_line(boundary_data['marine']['longitude'],\
                        boundary_data['marine']['latitude'],color='black',\
                        level='underlay',nonselection_line_alpha=1.0,\
                        nonselection_line_color='black')
    # shoreline boundaries
    map_view.multi_line(boundary_data['shoreline']['longitude'],\
                        boundary_data['shoreline']['latitude'],color='black',\
                        line_width=2, level='underlay',nonselection_line_alpha=1.0,\
                        nonselection_line_color='black')
    # state boundaries
    map_view.multi_line(boundary_data['state']['longitude'],\
                        boundary_data['state']['latitude'],color='black',\
                        level='underlay',nonselection_line_alpha=1.0,\
                        nonselection_line_color='black')
    # ------------------------------
    # add period label
    map_view.rect(style_parameter['map_view_period_box_lon'], style_parameter['map_view_period_box_lat'], \
                  width=style_parameter['map_view_period_box_width'], height=style_parameter['map_view_period_box_height'], \
                  width_units='screen',height_units='screen', color='#FFFFFF', line_width=1., line_color='black', level='underlay')
    map_view.text('lon', 'lat', 'map_period', source=map_data_one_slice_period_bokeh,\
                  text_font_size=style_parameter['annotating_text_font_size'],text_align='left',level='underlay')
    # ------------------------------
    # plot dots
    map_view.circle('map_lon_list', 'map_lat_list', color='map_data_one_slice', \
                    source=map_data_one_slice_bokeh, size=style_parameter['marker_size'],\
                    line_width=0.2, line_color='black', alpha=1.0,\
                    selection_color='map_data_one_slice', selection_line_color='black',\
                    selection_fill_alpha=1.0,\
                    nonselection_fill_alpha=1.0, nonselection_fill_color='map_data_one_slice',\
                    nonselection_line_color='black', nonselection_line_alpha=1.0)
    map_view.circle('lon', 'lat', color='color', source=selected_dot_on_map_bokeh, \
                    line_color='#00ff00', line_width=4.0, alpha=1.0, \
                    size=style_parameter['selected_marker_size'])
    # ------------------------------
    # change style
    map_view.title.text_font_size = style_parameter['title_font_size']
    map_view.title.align = 'center'
    map_view.title.text_font_style = 'normal'
    map_view.xaxis.axis_label = style_parameter['map_view_xlabel']
    map_view.xaxis.axis_label_text_font_style = 'normal'
    map_view.xaxis.axis_label_text_font_size = xlabel_fontsize
    map_view.xaxis.major_label_text_font_size = xlabel_fontsize
    map_view.yaxis.axis_label = style_parameter['map_view_ylabel']
    map_view.yaxis.axis_label_text_font_style = 'normal'
    map_view.yaxis.axis_label_text_font_size = xlabel_fontsize
    map_view.yaxis.major_label_text_font_size = xlabel_fontsize
    map_view.xgrid.grid_line_color = None
    map_view.ygrid.grid_line_color = None
    map_view.toolbar.logo = None
    map_view.toolbar_location = 'above'
    map_view.toolbar_sticky = False
    # ==============================
    # plot colorbar
    colorbar_fig = Figure(tools=[], y_range=(0,0.1),plot_width=style_parameter['map_view_plot_width'], \
                          plot_height=style_parameter['colorbar_plot_height'],title=style_parameter['colorbar_title'])
    colorbar_fig.toolbar_location=None
    colorbar_fig.quad(top='colorbar_top',bottom='colorbar_bottom',left='colorbar_left',right='colorbar_right',\
                      fill_color='palette_r',source=colorbar_data_one_slice_bokeh)
    colorbar_fig.yaxis[0].ticker=FixedTicker(ticks=[])
    colorbar_fig.xgrid.grid_line_color = None
    colorbar_fig.ygrid.grid_line_color = None
    colorbar_fig.xaxis.axis_label_text_font_size = xlabel_fontsize
    colorbar_fig.xaxis.major_label_text_font_size = xlabel_fontsize
    colorbar_fig.xaxis[0].formatter = PrintfTickFormatter(format="%5.2f")
    colorbar_fig.title.text_font_size = xlabel_fontsize
    colorbar_fig.title.align = 'center'
    colorbar_fig.title.text_font_style = 'normal'
    # ==============================
    curve_fig = Figure(plot_width=style_parameter['curve_plot_width'], plot_height=style_parameter['curve_plot_height'], \
                       y_range=(style_parameter['curve_y_min'],style_parameter['curve_y_max']), \
                       x_range=(style_parameter['curve_x_min'],style_parameter['curve_x_max']),x_axis_type='log',\
                        tools=['save','box_zoom','wheel_zoom','reset','crosshair','pan'],
                        title=style_parameter['curve_title'])
    # ------------------------------
    curve_fig.rect([style_parameter['curve_label_box_x']], [style_parameter['curve_label_box_y']], \
                   width=style_parameter['curve_label_box_width'], height=style_parameter['curve_label_box_height'], \
                   width_units='screen', height_units='screen', color='#FFFFFF', line_width=1., line_color='black', level='underlay')
    curve_fig.text('x', 'y', \
                   'lat_label', source=selected_curve_lat_label_bokeh)
    curve_fig.text('x', 'y', \
                   'lon_label', source=selected_curve_lon_label_bokeh)
    # ------------------------------
    curve_fig.line('curve_period', 'curve_velocity', source=selected_curve_data_bokeh, color='black')
    curve_fig.circle('curve_period', 'curve_velocity', source=selected_curve_data_bokeh, size=5, color='black')
    # ------------------------------
    curve_fig.title.text_font_size = style_parameter['title_font_size']
    curve_fig.title.align = 'center'
    curve_fig.title.text_font_style = 'normal'
    curve_fig.xaxis.axis_label = style_parameter['curve_xlabel']
    curve_fig.xaxis.axis_label_text_font_style = 'normal'
    curve_fig.xaxis.axis_label_text_font_size = xlabel_fontsize
    curve_fig.xaxis.major_label_text_font_size = xlabel_fontsize
    curve_fig.yaxis.axis_label = style_parameter['curve_ylabel']
    curve_fig.yaxis.axis_label_text_font_style = 'normal'
    curve_fig.yaxis.axis_label_text_font_size = xlabel_fontsize
    curve_fig.yaxis.major_label_text_font_size = xlabel_fontsize
    curve_fig.xgrid.grid_line_dash = [4, 2]
    curve_fig.ygrid.grid_line_dash = [4, 2]
    curve_fig.xaxis[0].formatter = PrintfTickFormatter(format="%4.0f")
    curve_fig.toolbar.logo = None
    curve_fig.toolbar_location = 'above'
    curve_fig.toolbar_sticky = False
    # ==============================
    map_data_one_slice_bokeh.callback = CustomJS(args=dict(selected_dot_on_map_bokeh=selected_dot_on_map_bokeh,\
                                                          map_data_one_slice_bokeh=map_data_one_slice_bokeh,\
                                                          selected_curve_data_bokeh=selected_curve_data_bokeh,\
                                                          curve_data_all_bokeh=curve_data_all_bokeh,\
                                                          selected_curve_lat_label_bokeh=selected_curve_lat_label_bokeh,\
                                                          selected_curve_lon_label_bokeh=selected_curve_lon_label_bokeh,\
                                                          all_curve_lat_label_bokeh=all_curve_lat_label_bokeh,\
                                                          all_curve_lon_label_bokeh=all_curve_lon_label_bokeh), code="""
    
    var inds = Math.round(cb_obj.selected['1d'].indices)
    
    selected_dot_on_map_bokeh.data['index'] = [inds]
    
    var new_slice = map_data_one_slice_bokeh.data
    
    selected_dot_on_map_bokeh.data['lat'] = [new_slice['map_lat_list'][inds]]
    selected_dot_on_map_bokeh.data['lon'] = [new_slice['map_lon_list'][inds]]
    selected_dot_on_map_bokeh.data['color'] = [new_slice['map_data_one_slice'][inds]]
    
    selected_dot_on_map_bokeh.change.emit()
    
    selected_curve_data_bokeh.data['curve_period'] = curve_data_all_bokeh.data['period_all'][inds]
    selected_curve_data_bokeh.data['curve_velocity'] = curve_data_all_bokeh.data['velocity_all'][inds]
    
    selected_curve_data_bokeh.change.emit()
    
    var all_lat_labels = all_curve_lat_label_bokeh.data['map_lat_label_list']
    var all_lon_labels = all_curve_lon_label_bokeh.data['map_lon_label_list']
    
    selected_curve_lat_label_bokeh.data['lat_label'] = [all_lat_labels[inds]]
    selected_curve_lon_label_bokeh.data['lon_label'] = [all_lon_labels[inds]]
    
    selected_curve_lat_label_bokeh.change.emit()
    selected_curve_lon_label_bokeh.change.emit()
    """)
    # ==============================
    period_slider_callback = CustomJS(args=dict(map_data_all_slices_bokeh=map_data_all_slices_bokeh,\
                                  map_data_one_slice_bokeh=map_data_one_slice_bokeh,\
                                  colorbar_data_all_slices_bokeh=colorbar_data_all_slices_bokeh, \
                                  colorbar_data_one_slice_bokeh=colorbar_data_one_slice_bokeh,\
                                  selected_dot_on_map_bokeh=selected_dot_on_map_bokeh,\
                                  map_data_one_slice_period_bokeh=map_data_one_slice_period_bokeh),\
                       code="""
    var p_index = Math.round(cb_obj.value)
    var map_data_all_slices = map_data_all_slices_bokeh.data
    
    
    var map_data_new_slice = map_data_all_slices['map_data_all_slices_color'][p_index]
    map_data_one_slice_bokeh.data['map_data_one_slice'] = map_data_new_slice
    map_data_one_slice_bokeh.change.emit()
    
    var color_data_all_slices = colorbar_data_all_slices_bokeh.data
    colorbar_data_one_slice_bokeh.data['colorbar_left'] = color_data_all_slices['colorbar_data_all_left'][p_index]
    colorbar_data_one_slice_bokeh.data['colorbar_right'] = color_data_all_slices['colorbar_data_all_right'][p_index]
    colorbar_data_one_slice_bokeh.change.emit()
    
    var selected_index = selected_dot_on_map_bokeh.data['index']
    selected_dot_on_map_bokeh.data['color'] = [map_data_new_slice[selected_index]]
    selected_dot_on_map_bokeh.change.emit()
    
    map_data_one_slice_period_bokeh.data['map_period'] = [map_data_all_slices['map_data_all_slices_period'][p_index]]
    map_data_one_slice_period_bokeh.change.emit()
    """)
    period_slider = Slider(start=0, end=nperiod-1, value=style_parameter['map_view_default_index'], \
                           step=1, title=style_parameter['period_slider_title'], \
                           width=style_parameter['period_slider_plot_width'],\
                           height=50, callback=period_slider_callback)
    
    # ==============================
    curve_slider_callback = CustomJS(args=dict(selected_dot_on_map_bokeh=selected_dot_on_map_bokeh,\
                                              map_data_one_slice_bokeh=map_data_one_slice_bokeh,\
                                              selected_curve_data_bokeh=selected_curve_data_bokeh,\
                                              curve_data_all_bokeh=curve_data_all_bokeh,\
                                              selected_curve_lat_label_bokeh=selected_curve_lat_label_bokeh,\
                                              selected_curve_lon_label_bokeh=selected_curve_lon_label_bokeh,\
                                              all_curve_lat_label_bokeh=all_curve_lat_label_bokeh,\
                                              all_curve_lon_label_bokeh=all_curve_lon_label_bokeh),\
                                    code="""
    var c_index = Math.round(cb_obj.value)
    
    var one_slice = map_data_one_slice_bokeh.data
    
    selected_dot_on_map_bokeh.data['index'] = [c_index]
    selected_dot_on_map_bokeh.data['lat'] = [one_slice['map_lat_list'][c_index]]
    selected_dot_on_map_bokeh.data['lon'] = [one_slice['map_lon_list'][c_index]]
    selected_dot_on_map_bokeh.data['color'] = [one_slice['map_data_one_slice'][c_index]]
    
    selected_dot_on_map_bokeh.change.emit()
    
    selected_curve_data_bokeh.data['curve_period'] = curve_data_all_bokeh.data['period_all'][c_index]
    selected_curve_data_bokeh.data['curve_velocity'] = curve_data_all_bokeh.data['velocity_all'][c_index]
    
    selected_curve_data_bokeh.change.emit()
    
    var all_lat_labels = all_curve_lat_label_bokeh.data['map_lat_label_list']
    var all_lon_labels = all_curve_lon_label_bokeh.data['map_lon_label_list']
    
    selected_curve_lat_label_bokeh.data['lat_label'] = [all_lat_labels[c_index]]
    selected_curve_lon_label_bokeh.data['lon_label'] = [all_lon_labels[c_index]]
    
    selected_curve_lat_label_bokeh.change.emit()
    selected_curve_lon_label_bokeh.change.emit()
    """)
    curve_slider = Slider(start=0, end=ncurve-1, value=style_parameter['curve_default_index'], \
                          step=1, title=style_parameter['curve_slider_title'], width=style_parameter['curve_plot_width'],\
                          height=50, callback=curve_slider_callback)
    
    # ==============================
    # annotating text
    annotating_fig01 = Div(text=style_parameter['annotating_html01'], \
        width=style_parameter['annotation_plot_width'], height=style_parameter['annotation_plot_height'])
    annotating_fig02 = Div(text=style_parameter['annotating_html02'],\
        width=style_parameter['annotation_plot_width'], height=style_parameter['annotation_plot_height'])
    # ==============================
    output_file(filename,title=style_parameter['html_title'],mode=style_parameter['library_source'])
    left_fig = Column(period_slider, map_view, colorbar_fig, annotating_fig01,\
                    width=style_parameter['left_column_width'] )
    right_fig = Column(curve_slider, curve_fig, annotating_fig02, \
                    width=style_parameter['right_column_width'] )
    layout = Row(left_fig, right_fig)
    save(layout)
Beispiel #19
0
    def create_objects(cls, symbol, df, securities):
        descr_box = Paragraph(text='content loading...')

        btn_close_loading = Button(label='Close Loading')
        dialog_loading = Dialog(title='loading',
                                content=vplot(descr_box),
                                name='loading_dialog',
                                buttons=[btn_close_loading],
                                visible=False)

        source_data = dict(df)
        main_source = ColumnDataSource(dict(df))
        source = ColumnDataSource(source_data)

        # TODO: REMOVE THIS COMMENTED CODE! IT'S JUST THE PREVIOUS
        # VERSION USED BEFORE NEW P&D Cached results and algorithm
        # get the cached results of the P&D algorithm computed with the
        # "default" configuration
        # intervals = utils.cached_pumps.get(symbol, pumps.to_dicts(((),(),(),(),(),())))
        # intervals['bottom'] = [0] * len(intervals['start'])
        # intervals['values'] = [max(df['price'])] * len(intervals['start'])
        #
        # intervals = pd.DataFrame(intervals)

        # new version
        stats = utils.get_symbols_cached_stats()[symbol]
        intervals = pd.DataFrame(stats)
        intervals['bottom'] = [0] * len(intervals['start'])
        intervals['values'] = [max(df['price'])] * len(intervals['start'])

        conv = lambda x: utils.to_seconds(pd.to_datetime(x))

        intervals = intervals[
            (pd.to_datetime(intervals['start']) > conv(config.date_range[0])) &
            (pd.to_datetime(intervals['start']) < conv(config.date_range[1]))]

        # Create P&Ds intervals DataSource
        intervals_source = ColumnDataSource(intervals)
        source.tags = ['main_source']

        trends = utils.load_trends_data(symbol, start_date=min(df['dt']))
        trends_source = ColumnDataSource(trends)

        trades = Slider(title="trades",
                        name='trades',
                        value=0,
                        start=0,
                        end=124,
                        step=1)

        # Selectors
        symbol = Select.create(options=securities,
                               value=symbol,
                               name='symbol',
                               title="")
        window_selector = Select.create(options=['---'],
                                        name='period_selector',
                                        title="Search intervals with:")
        symbol_filter = Select.create(
            options=['All', 'Stocks with Spam', 'Stocks without Spam'],
            name='symbol_filter',
            title="Filter Symbols:",
            value='Stocks with Spam')
        callback = Callback(args={
            'symbol_filter': symbol_filter,
            'dialog_loading': dialog_loading
        },
                            code=callbacks.symbol_filter)
        symbol_filter.callback = callback

        btn_detect_pumps = Button(label='Configure P&D Detection',
                                  name='config_pumps')

        main_tab = Panel(title="Main")
        tabs = Tabs()

        # Create STOCKS TABLE
        ranks = utils.get_pumps_rank()
        # quotient_metrics = utils.get_quotient_metrics()
        # ranks['quotient'] = quotient_metrics['quotient']

        foo = lambda x: utils.spams_count.get(x, 0)
        ranks['spams'] = map(foo, ranks['symbol'])
        ranks = ranks.sort(['spams', 'vol_quotient'], ascending=False)

        cls._pre_filtered_ranks = {
            'All': {k: ranks[k]
                    for k in ranks.columns},
            'Stocks with Spam':
            dict(ranks[ranks['spams'] > 0].sort('vol_quotient',
                                                ascending=False)),
            'Stocks without Spam':
            dict(ranks[ranks['spams'] == 0].sort('vol_quotient',
                                                 ascending=False)),
        }

        source_stocks_rank = ColumnDataSource(cls._pre_filtered_ranks['All'])

        table_stocks_rank = DataTable(
            source=source_stocks_rank,
            width=560,
            height=450,
            selectable=True,
            editable=True,
            columns=[
                TableColumn(field='symbol',
                            title='symbol',
                            width=130,
                            editor=StringEditor()),
                TableColumn(field='vol_quotient',
                            title='volume ratio',
                            editor=StringEditor(),
                            default_sort='descending'),
                TableColumn(field='risk_score',
                            title='risk',
                            width=100,
                            editor=StringEditor(),
                            default_sort='descending'),
                TableColumn(field='spams',
                            title='spams',
                            width=130,
                            editor=StringEditor(),
                            default_sort='descending'),
            ])

        callback = Callback(args={
            'tr': table_stocks_rank,
            'sr': source_stocks_rank,
            'symb': symbol,
            'dialog_loading': dialog_loading
        },
                            code=callbacks.source_stocks_rank)
        source_stocks_rank.callback = callback

        return locals()
Beispiel #20
0
def paired_plots(data, title=None, text_cols=['seqname']):
    """Create an interactive scatterplot. ``data`` is a pandas dataframe
    with (at least) column 'dist' in addition to columns
    containing other features. ``text_cols`` is a list of columns to
    include in the DataTable.

    Returns a pair of plot objects (plt, tab).

    """
    data['i'] = range(len(data))
    data = data.fillna('')
    data['select_alpha'] = data['is_type'].apply(lambda x: 0 if x else 1)
    data['unselect_alpha'] = data['is_type'].apply(lambda x: 0 if x else 0.2)
    data['out_alpha'] = data['is_out'].apply(lambda x: 1 if x else 0)
    data['size'] = 10
    data['triangle_size'] = data['size'] * 1.1

    source = ColumnDataSource(data=data)
    types = ColumnDataSource(data=data[data['is_type']])
    # start with is_outs in table
    table_rows = ColumnDataSource(data=data[data['is_out']])

    tools = [
        'box_select', 'lasso_select', 'resize', 'box_zoom', 'pan', 'reset',
        'tap'
    ]

    step_plt = figure(
        title=title,
        plot_width=600,
        plot_height=600,
        tools=tools,
        x_axis_label='rank order',
        y_axis_label='distance to centroid (%)',
    )

    # underlying markers are visible only when selected
    step_plt.scatter(source=ColumnDataSource(data=data[data['is_out']]),
                     x='i',
                     y='dist_from_cent',
                     color='red',
                     fill_alpha='out_alpha',
                     line_alpha='select_alpha',
                     marker='circle',
                     size='size')

    # underlying markers are visible only when selected
    step_plt.scatter(source=table_rows,
                     fill_alpha=0,
                     line_alpha='select_alpha',
                     x='i',
                     y='dist_from_cent',
                     color='gray',
                     marker='circle',
                     size='size')

    step_plt.scatter(source=types,
                     fill_alpha='out_alpha',
                     color='red',
                     line_alpha=1,
                     line_color='red',
                     x='i',
                     y='dist_from_cent',
                     marker='triangle',
                     size='triangle_size')

    step_plt.scatter(source=source,
                     fill_alpha=0,
                     line_alpha='unselect_alpha',
                     line_color='gray',
                     x='i',
                     y='dist_from_cent',
                     marker='circle',
                     size='size')

    pca_plt = figure(title=None,
                     plot_width=600,
                     plot_height=600,
                     tools=tools,
                     x_axis_label='distance',
                     y_axis_label='distance')

    pca_plt.circle(
        source=ColumnDataSource(data=data[data['is_out']]),
        size='size',
        fill_alpha='out_alpha',
        line_alpha='select_alpha',
        x='x',
        y='y',
        color='red',
    )

    # underlying markers are visible only when selected
    pca_plt.circle(
        source=table_rows,
        line_alpha='select_alpha',
        fill_alpha=0,
        size='size',
        x='x',
        y='y',
        color='gray',
    )

    pca_plt.triangle(
        source=types,
        line_color='red',
        fill_alpha='out_alpha',
        line_alpha=1,
        size='triangle_size',
        x='x',
        y='y',
    )

    pca_plt.circle(
        source=source,
        fill_alpha=0,
        line_alpha='unselect_alpha',
        line_color='gray',
        size='size',
        x='x',
        y='y',
    )

    formatters = {
        'seqname':
        bokeh.models.widgets.tables.HTMLTemplateFormatter(
            template='<a href="https://www.ncbi.nlm.nih.gov/nuccore/'
            '<%= version %>">'
            '<div title="<%= value %>"><%= value %></div></a>'),
        'type strain hit':
        bokeh.models.widgets.tables.HTMLTemplateFormatter(),
        'description':
        bokeh.models.widgets.tables.HTMLTemplateFormatter(
            template='<div title="<%= value %>"><%= value %></div>'),
        'identity':
        bokeh.models.widgets.tables.NumberFormatter(format='0.0%'),
        'dist':
        bokeh.models.widgets.tables.NumberFormatter(format='0.00%')
    }

    tab = DataTable(source=table_rows,
                    columns=[
                        TableColumn(field=col,
                                    title=TABLE_HEADER.get(col, col),
                                    width=TABLE_WIDTHS[col],
                                    formatter=formatters.get(col, None))
                        for col in text_cols
                    ],
                    fit_columns=False,
                    row_headers=False,
                    width=1200,
                    height=1200,
                    sortable=True)

    code = """
        var inds = cb_obj.selected['1d'].indices;
        var data = source.data;
        var text_data = text_source.data;

        for (var column in text_data){
            text_data[column] = [];
            for (var i = 0; i < inds.length; i++) {
                var ind = inds[i];
                text_data[column].push(data[column][ind])
            }
        }

        source.trigger('change');
        text_source.trigger('change');
        table.trigger('change');
        """

    # note that the callback is added to the source for the scatter plot only
    source.callback = CustomJS(args=dict(source=source,
                                         table=tab,
                                         text_source=table_rows),
                               code=code)

    return step_plt, pca_plt, tab
Beispiel #21
0
def draw_bokeh(X, cluster, sentences):
    """Dimension reduction with PCA and plotting with bokeh """

    X_reduced = PCA(n_components=2).fit_transform(X)

    colors = [Category10[10][i % 10] for i in cluster.labels_]
    sizes = np.ones(len(X)) * 10
    sizes[cluster.cluster_centers_indices_] = 20

    source = ColumnDataSource(data=dict(
        eigenv1=[x[0] for x in X_reduced],
        eigenv2=[x[1] for x in X_reduced],
        s=sentences,
        c=colors,
        size=sizes,
    ))

    hover = HoverTool(tooltips=[("index",
                                 "$index"), ("(x,y)",
                                             "@eigenv1, @eigenv2)"), ("s",
                                                                      "@s")])

    p = figure(title="reforma_educativa",
               tools=[hover, ResetTool(), BoxSelectTool()])
    p.toolbar.logo = None
    p.xaxis.axis_label = '1st eigenv'
    p.yaxis.axis_label = '2nd eigenv'
    p.scatter('eigenv1',
              'eigenv2',
              size='size',
              fill_color='c',
              fill_alpha=1,
              line_color='c',
              nonselection_fill_color="c",
              nonselection_fill_alpha=0.5,
              source=source)

    div = Div(width=600)

    text_input = TextAreaInput(title="Text: ", rows=50, max_length=2000)

    layout = row(p, div, text_input)

    source.callback = CustomJS(args=dict(source=source,
                                         div=div,
                                         sentences=sentences,
                                         colors=colors),
                               code="""
            var inds = source.selected.indices
            div.text = ""
            for (var i = 0; i < sentences.length; i++) {
                if (inds.includes(i)) {
                    div.text += '<p style="background-color:' + colors[i] + ';">' + sentences[i] + "</p>"
                }
                else {
                    r = parseInt(colors[i].substring(1, 3), 16)
                    g = parseInt(colors[i].substring(3, 5), 16)
                    b = parseInt(colors[i].substring(5, 7), 16)
                    a = 0.3
                    rgba = r  + "," + g + "," + b + "," + a
                    div.text += '<p style="background-color:rgba(' + rgba + ');">' + sentences[i] + "</p>"
                }   
            }
        """)

    output_file("reforma_educativa.html", title="Sentence embedding example")

    show(layout)