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

# ##TODO:  T2.2 Add hovering tooltips to display date, canton and averaged daily new case

# # (Hovertip doc) https://docs.bokeh.org/en/latest/docs/user_guide/tools.html#hovertool
# # (Date hover)https://stackoverflow.com/questions/41380824/python-bokeh-hover-date-time
hover = HoverTool(
    tooltips=[
        ('date', '@x{%F}'),
        ('canton', canton),  # use @{ } for field names with spaces
        ('cases', '@y'),
    ],
    formatters={
        '@x': 'datetime',  # use 'datetime' formatter for '@date' field
        '@{adj cases}':
        'printf',  # use 'printf' formatter for '@{adj close}' field
        # use default 'numeral' formatter for other fields
    },

    # display a tooltip whenever the cursor is vertically in line with a glyph
    # mode='vline'
)

p.add_tools(hover)

show(p)
output_file("dvc_ex2.html")
save(p)

# hide / mute glyphs - https://docs.bokeh.org/en/latest/docs/user_guide/interaction/legends.html
示例#2
0
def assembly_chart(df, complements):
    """function to assembly the chart"""
    print('starting the plot...')

    # specify the output file name
    output_file("movigrama_chart.html")
    # force to show only one plot when multiples executions of the code occur
    # otherwise the plots will append each time one new calling is done
    reset_output()

    # create ColumnDataSource objects directly from Pandas data frames
    source = ColumnDataSource(df)

    # use the column DT as index
    df.set_index('DT', inplace=True)

    ###########################################################################
    #
    #  Movigrama Plot
    #
    ###########################################################################

    # build figure of the plot
    p = figure(x_axis_type='datetime',
               x_axis_label='days of moviment',
               y_axis_label='unities movimented',
               plot_width=1230,
               plot_height=500,
               active_scroll='wheel_zoom')

    # TODO Specify X range (not all plots have 365 days of moviment)

    # build the Stock Level bar
    r1 = p.vbar(x='DT',
                bottom=0,
                top='STOCK',
                width=pd.Timedelta(days=1),
                fill_alpha=0.4,
                color='paleturquoise',
                source=source)

    # build the OUT bar
    p.vbar(x='DT',
           bottom=0,
           top='SOMA_SAI',
           width=pd.Timedelta(days=1),
           fill_alpha=0.8,
           color='crimson',
           source=source)

    # build the IN bar
    p.vbar(x='DT',
           bottom=0,
           top='SOMA_ENTRA',
           width=pd.Timedelta(days=1),
           fill_alpha=0.8,
           color='seagreen',
           source=source)

    # edit title
    # adds warehouse title
    p.add_layout(
        Title(text=complements['warehouse'],
              text_font='helvetica',
              text_font_size='10pt',
              text_color='orangered',
              text_alpha=0.5,
              align='center',
              text_font_style="italic"), 'above')
    # adds product title
    p.add_layout(
        Title(text=complements['product'],
              text_font='helvetica',
              text_font_size='10pt',
              text_color='orangered',
              text_alpha=0.5,
              align='center',
              text_font_style="italic"), 'above')
    # adds main title
    p.add_layout(
        Title(text='Movigrama Endicon',
              text_font='helvetica',
              text_font_size='16pt',
              text_color='orangered',
              text_alpha=0.9,
              align='center',
              text_font_style="bold"), 'above')

    # adds horizontal line
    hline = Span(location=0,
                 line_alpha=0.4,
                 dimension='width',
                 line_color='gray',
                 line_width=3)
    p.renderers.extend([hline])

    # adapt the range to the plot
    p.x_range.range_padding = 0.1
    p.y_range.range_padding = 0.1

    # format the plot's outline
    p.outline_line_width = 4
    p.outline_line_alpha = 0.1
    p.outline_line_color = 'orangered'

    # format major labels
    p.axis.major_label_text_color = 'gray'
    p.axis.major_label_text_font_style = 'bold'

    # format labels
    p.axis.axis_label_text_color = 'gray'
    p.axis.axis_label_text_font_style = 'bold'

    #    p.xgrid.grid_line_color = None  # disable vertical bars
    #    p.ygrid.grid_line_color = None  # disable horizontal bars

    # change placement of minor and major ticks in the plot
    p.axis.major_tick_out = 10
    p.axis.minor_tick_in = -3
    p.axis.minor_tick_out = 6
    p.axis.minor_tick_line_color = 'gray'

    # format properly the X datetime axis
    p.xaxis.formatter = DatetimeTickFormatter(days=['%d/%m'],
                                              months=['%m/%Y'],
                                              years=['%Y'])

    # initiate hover object
    hover = HoverTool()
    hover.mode = "vline"  # activate hover by vertical line
    hover.tooltips = [("SUM-IN", "@SOMA_ENTRA"), ("SUM-OUT", "@SOMA_SAI"),
                      ("COUNT-IN", "@TRANSACT_ENTRA"),
                      ("COUNT-OUT", "@TRANSACT_SAI"), ("STOCK", "@STOCK"),
                      ("DT", "@DT{%d/%m/%Y}")]
    # use 'datetime' formatter for 'DT' field
    hover.formatters = {"DT": 'datetime'}
    hover.renderers = [r1]  # display tooltip only to one render
    p.add_tools(hover)

    ###########################################################################
    #
    #  Demand analysis
    #
    ###########################################################################

    # change to positive values
    df['out_invert'] = df['SOMA_SAI'] * -1
    # moving average with n=30 days
    df['MA30'] = df['out_invert'].rolling(30).mean().round(0)
    # moving standard deviation with n=30 days
    df['MA30_std'] = df['out_invert'].rolling(30).std().round(0)
    # lower control limit for 1 sigma deviation
    df['lcl_1sigma'] = (df['MA30'] - df['MA30_std'])
    # upper control limit for 1 sigma deviation
    df['ucl_1sigma'] = (df['MA30'] + df['MA30_std'])

    source = ColumnDataSource(df)

    p1 = figure(plot_width=1230,
                plot_height=500,
                x_range=p.x_range,
                x_axis_type="datetime",
                active_scroll='wheel_zoom')

    # build the Sum_out bar
    r1 = p1.vbar(x='DT',
                 top='out_invert',
                 width=pd.Timedelta(days=1),
                 color='darkred',
                 line_color='salmon',
                 fill_alpha=0.4,
                 source=source)

    # build the moving average line
    p1.line(x='DT', y='MA30', source=source)

    # build the confidence interval
    band = Band(base='DT',
                lower='lcl_1sigma',
                upper='ucl_1sigma',
                source=source,
                level='underlay',
                fill_alpha=1.0,
                line_width=1,
                line_color='black')
    p1.renderers.extend([band])

    # adds title
    p1.add_layout(
        Title(text='Demand Variability',
              text_font='helvetica',
              text_font_size='16pt',
              text_color='orangered',
              text_alpha=0.5,
              align='center',
              text_font_style="bold"), 'above')

    # adds horizontal line
    hline = Span(location=0,
                 line_alpha=0.4,
                 dimension='width',
                 line_color='gray',
                 line_width=3)
    p1.renderers.extend([hline])

    # format the plot's outline
    p1.outline_line_width = 4
    p1.outline_line_alpha = 0.1
    p1.outline_line_color = 'orangered'

    # format major labels
    p1.axis.major_label_text_color = 'gray'
    p1.axis.major_label_text_font_style = 'bold'

    # format labels
    p1.axis.axis_label_text_color = 'gray'
    p1.axis.axis_label_text_font_style = 'bold'

    # change placement of minor and major ticks in the plot
    p1.axis.major_tick_out = 10
    p1.axis.minor_tick_in = -3
    p1.axis.minor_tick_out = 6
    p1.axis.minor_tick_line_color = 'gray'

    # format properly the X datetime axis
    p1.xaxis.formatter = DatetimeTickFormatter(days=['%d/%m'],
                                               months=['%m/%Y'],
                                               years=['%Y'])

    # initiate hover object
    hover = HoverTool()
    hover.mode = "vline"  # activate hover by vertical line
    hover.tooltips = [("DEMAND", '@out_invert'), ("UCL 1σ", "@ucl_1sigma"),
                      ("LCL 1σ", "@lcl_1sigma"), ("M AVG 30d", "@MA30"),
                      ("DT", "@DT{%d/%m/%Y}")]
    # use 'datetime' formatter for 'DT' field
    hover.formatters = {"DT": 'datetime'}
    hover.renderers = [r1]  # display tooltip only to one render
    p1.add_tools(hover)

    ###########################################################################
    #
    #  Demand grouped by month
    #
    ###########################################################################

    resample_M = df.iloc[:, 0:6].resample('M').sum()  # resample to month
    # create column date as string
    resample_M['date'] = resample_M.index.strftime('%b/%y').values
    # moving average with n=3 months
    resample_M['MA3'] = resample_M['out_invert'].rolling(3).mean()

    resample_M['MA3'] = np.ceil(resample_M.MA3)  # round up the column MA3
    # resample to month with mean
    resample_M['mean'] = np.ceil(resample_M['out_invert'].mean())
    # resample to month with standard deviation
    resample_M['std'] = np.ceil(resample_M['out_invert'].std())
    # moving standard deviation with n=30 days
    resample_M['MA3_std'] = np.ceil(resample_M['out_invert'].rolling(3).std())
    # lower control limit for 1 sigma deviation
    resample_M['lcl_1sigma'] = resample_M['MA3'] - resample_M['MA3_std']
    # upper control limit for 1 sigma deviation
    resample_M['ucl_1sigma'] = resample_M['MA3'] + resample_M['MA3_std']

    source = ColumnDataSource(resample_M)

    p2 = figure(plot_width=1230,
                plot_height=500,
                x_range=FactorRange(factors=list(resample_M.date)),
                title='demand groupped by month')

    colors = factor_cmap('date',
                         palette=Category20_20,
                         factors=list(resample_M.date))

    p2.vbar(x='date',
            top='out_invert',
            width=0.8,
            fill_color=colors,
            fill_alpha=0.8,
            source=source,
            legend=value('OUT'))

    p2.line(x='date',
            y='MA3',
            color='red',
            line_width=3,
            line_dash='dotted',
            source=source,
            legend=value('MA3'))

    p2.line(x='date',
            y='mean',
            color='blue',
            line_width=3,
            line_dash='dotted',
            source=source,
            legend=value('mean'))

    band = Band(base='date',
                lower='lcl_1sigma',
                upper='ucl_1sigma',
                source=source,
                level='underlay',
                fill_alpha=1.0,
                line_width=1,
                line_color='black')

    labels1 = LabelSet(x='date',
                       y='MA3',
                       text='MA3',
                       level='glyph',
                       y_offset=5,
                       source=source,
                       render_mode='canvas',
                       text_font_size="8pt",
                       text_color='darkred')

    labels2 = LabelSet(x='date',
                       y='out_invert',
                       text='out_invert',
                       level='glyph',
                       y_offset=5,
                       source=source,
                       render_mode='canvas',
                       text_font_size="8pt",
                       text_color='gray')

    low_box = BoxAnnotation(
        top=resample_M['mean'].iloc[0] -
        resample_M['std'].iloc[0],  # analysis:ignore
        fill_alpha=0.1,
        fill_color='red')
    mid_box = BoxAnnotation(
        bottom=resample_M['mean'].iloc[0] -
        resample_M['std'].iloc[0],  # analysis:ignore
        top=resample_M['mean'].iloc[0] +
        resample_M['std'].iloc[0],  # analysis:ignore
        fill_alpha=0.1,
        fill_color='green')
    high_box = BoxAnnotation(
        bottom=resample_M['mean'].iloc[0] +
        resample_M['std'].iloc[0],  # analysis:ignore
        fill_alpha=0.1,
        fill_color='red')

    p2.renderers.extend([band, labels1, labels2, low_box, mid_box, high_box])
    p2.legend.click_policy = "hide"
    p2.legend.background_fill_alpha = 0.4

    p2.add_layout(
        Title(text='Demand Grouped by Month',
              text_font='helvetica',
              text_font_size='16pt',
              text_color='orangered',
              text_alpha=0.5,
              align='center',
              text_font_style="bold"), 'above')

    # adds horizontal line
    hline = Span(location=0,
                 line_alpha=0.4,
                 dimension='width',
                 line_color='gray',
                 line_width=3)
    p2.renderers.extend([hline])

    # format the plot's outline
    p2.outline_line_width = 4
    p2.outline_line_alpha = 0.1
    p2.outline_line_color = 'orangered'

    # format major labels
    p2.axis.major_label_text_color = 'gray'
    p2.axis.major_label_text_font_style = 'bold'

    # format labels
    p2.axis.axis_label_text_color = 'gray'
    p2.axis.axis_label_text_font_style = 'bold'

    # change placement of minor and major ticks in the plot
    p2.axis.major_tick_out = 10
    p2.axis.minor_tick_in = -3
    p2.axis.minor_tick_out = 6
    p2.axis.minor_tick_line_color = 'gray'

    # initiate hover object
    # TODO develop hoverTool
    #    hover = HoverTool()
    #    hover.mode = "vline"  # activate hover by vertical line
    #    hover.tooltips = [("SUM-IN", "@SOMA_ENTRA"),
    #                      ("SUM-OUT", "@SOMA_SAI"),
    #                      ("COUNT-IN", "@TRANSACT_ENTRA"),
    #                      ("COUNT-OUT", "@TRANSACT_SAI"),
    #                      ("STOCK", "@STOCK")]
    #    hover.renderers = [r1]  # display tooltip only to one render
    #    p2.add_tools(hover)

    ###########################################################################
    #
    #  Plot figures
    #
    ###########################################################################

    # put the results in a column and show
    show(column(p, p1, p2))

    # show(p)  # plot action

    print('plot finished')
from bokeh.plotting import figure, show, output_file
from bokeh.models import HoverTool
from seaborn.regression import _RegressionPlotter

tips = sns.load_dataset("tips")
tips.sort_values(by='total_bill', inplace=True)

regplot = _RegressionPlotter('total_bill', 'tip', data=tips)
grid, yhat, err_bands = regplot.fit_regression(grid=tips.total_bill)

tips['yhat'] = yhat
tips['ci1'] = err_bands[0]
tips['ci2'] = err_bands[1]

hover = HoverTool(tooltips=[
    ("(x, y)", "($x, $y)"),
])
tools = [hover, 'pan', 'wheel_zoom']

p = figure(title="Bokeh Regplot", toolbar_location='right', tools=tools)

p.scatter('total_bill', 'tip', source=tips)
p.line('total_bill', 'yhat', source=tips, line_width=2, line_color='grey')
p.line('total_bill',
       'ci1',
       source=tips,
       alpha=0.7,
       line_color='grey',
       line_dash='dashed')
p.line('total_bill',
       'ci2',
示例#4
0
# 'html' stores the blockquote code
embed_dict = {}
with io.open('embed_code.txt', 'rt', encoding='utf-8') as embed_file:
    embed_dict = json.loads(embed_file.read())

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

# tweet tags (topic, popularity, similarity)
tweet_tags = pandas.DataFrame(numpy.random.rand(len(tweet_list), 2),
                              columns={'x', 'y'})
tweet_tags['tweet_id'] = [item['id_str'] for item in tweet_list]

# build the plot
plot_source = ColumnDataSource(data=dict(
    x=tweet_tags['x'], y=tweet_tags['y'], tid=tweet_tags['tweet_id']))
hover = HoverTool(tooltips=[('index', '$index'), ('tweet_id', '@tid')])
p = figure(plot_width=500,
           tools=[
               PanTool(),
               WheelZoomTool(), hover,
               ResetTool(),
               TapTool(),
               LassoSelectTool()
           ])
p.circle('x', 'y', source=plot_source)
# scr, di = components(p)

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)
示例#5
0
    df_labels = pd.read_csv('~/Downloads/network_classification/src/data/tsne_label_data.csv')

    # Create cross tabulation of tsne data and print
    df1 = pd.DataFrame({'labels': df_labels['Label'], 'Collection': df_labels['Category Name']})
    print("Crosstab for t-SNE data:\n")
    ct = pd.crosstab(df1['Collection'], df1['labels'])
    print(ct)

    data = {'x': xs, 'y': ys, 'Collection': category, 'Graph': names}
    df = pd.DataFrame(data)

    df.to_csv('~/Downloads/network_classification/src/data/tsne_canberra_coord_700_2.csv')

    # Create hover tool
    hover = HoverTool()
    hover.tooltips = [("Graph", "@Graph"), ("Category", "@{Collection}")]

    # Creating the scatter plot of the x and y coordinates
    m = figure(title = 't-SNE using Canberra Distance', plot_width=1000)

    # Color the plot by collection
    category = df['Collection']
    all_categories = category.unique().tolist()
    for i, graph in enumerate(all_categories):
        source = ColumnDataSource(df[df['Collection'] == graph])
        m.circle(x='x', y='y', source=source, color=d3['Category20'][16][i], size=8, legend=graph)

    # Creating scatter plot of centroids
    m.square_cross(centroids_x, centroids_y, color ='black', size = 12, legend = 'Centroid')
        TableColumn(field="koi_dor",
                    title="a/rstar",
                    formatter=NumberFormatter(format="0.00")),
        TableColumn(field="koi_score",
                    title="Disp Score",
                    formatter=NumberFormatter(format="0.00"))
    ]
    # Make the bokeh data table
    data_table = DataTable(source=source,
                           columns=columns,
                           height=300,
                           width=1000)

    # Do the Figure initially it is log period vs log planet radius
    # Include hovertool
    hover = HoverTool(tooltips=[("KOI", "@koi_number{0.00}")])

    data_figure = figure(height=600, width=1000,x_axis_label='Log Period [Day]', \
                    y_axis_label='Log Rp [Rearth]', tools=[hover, TapTool(), BoxZoomTool(), PanTool(), ZoomOutTool(), ZoomInTool(), ResetTool(), SaveTool()])
    data_figure.axis.axis_line_width = 3
    circle_handle = data_figure.circle(x='Logkoi_period',
                                       y='Logkoi_prad',
                                       source=source,
                                       size=10)
    data_figure.axis.axis_label_text_font_size = "20pt"
    data_figure.axis.major_label_text_font_size = "15pt"
    data_figure.axis.major_tick_line_width = 3
    xAxisHandle = data_figure.axis[0]
    yAxisHandle = data_figure.axis[1]
    # Include tap tool to open url with click on point
    taptool = data_figure.select(type=TapTool)
            allow_pickle=True))

miri = {'imaging': miri_imaging, 'mrs': miri_mrs, 'lrs': miri_lrs}
nircam = {'sw': nircam_sw, 'lw': nircam_lw, 'wfgrism': nircam_wfgrism}
niriss = {
    'imaging': niriss_imaging,
    'wfss': niriss_wfss,
    'soss': niriss_soss,
    'ami': niriss_ami
}
nirspec = {'fs': nirspec_fs, 'ifu': nirspec_ifu, 'msa': nirspec_msa}

frame = {'nirspec': nirspec, 'miri': miri, 'nircam': nircam, 'niriss': niriss}

hover = HoverTool(tooltips=[("Mode", "@label"), (
    "Configuration", "@config"), ("Wavelength",
                                  "@x"), ("Flux Density",
                                          "@y Jy"), ("AB magnitude", "@ymag")])
TOOLS = ['box_zoom', hover, 'reset']

colors = {
    'miri': ColorPalette[8][0],
    'nircam': ColorPalette[8][1],
    'niriss': ColorPalette[8][2],
    'nirspec': ColorPalette[8][3]
}

yrange = (10**-4, 10**3.2)
plot = Figure(x_axis_type="log",
              y_axis_type="log",
              y_range=yrange,
              x_range=(0.4, 29.),
示例#8
0
    'Number of Permits': total_permits,
    'Mean Permit Value': mean_permit_value,
    'Median Permit Value': median_permit_value,
    'Delta Housing Units': delta_housing_units
}

agg_method = Select(title='Aggregation Method',
                    value="Number of Permits",
                    options=list(methods))

# Create Column Data Source that will be used by the plot
source = ColumnDataSource(
    data=dict(xs=[], ys=[], color=[], alpha=[], value=[]))

hover = HoverTool(tooltips=[
    ("Value", "@value"),
])

p = Figure(plot_height=700,
           plot_width=700,
           title="",
           x_range=[-94.9, -94.25],
           y_range=[38.8, 39.45],
           tools=[hover, 'wheel_zoom', 'reset', 'pan'])
p.patches(xs="xs",
          ys="ys",
          source=source,
          fill_color="color",
          fill_alpha='alpha',
          line_color=None)
示例#9
0
def stack_bar(participation_values, member, labels, metric, choose):
    """
    Creates a stacked bar graph showing percentages of participation for each member for each day/week + hover
    :param participation_values: Dict{ Member : { date : {'turns': float, 'speak, float } }, Member : ... }
    :param member: Member who is viewing the report (serves as base of bar stacks). Either..
    - member key if no member_names dictionary is given, or
    - member name if member_names dictionary is given
    :param labels: List[date1, date2, ..., 'Average']
    :param metric: turns' or 'speak' (Whether you want to use Turns or Speaking Time)
    :param choose: Whether or not to add Date Picker to choose dates
    :return: bokeh plot
    """
    colors = brewer['Set2'][len(participation_values)]
    members = {}  # To order members
    data = {}
    bottoms = {}
    color_members = {}
    for date in labels:
        bottoms[date] = 0
    if member:
        # Order the members so that 'member' is always on the bottom of the stacked bar graph, and so that bars
        # will always be stacked in the same order.
        # members is a dictionary, e.g. {'0': 'Member1', '1': 'Member2', etc... }
        # color_members is a dictionary, e.g. {'Member1': 'color_hex_value_1', 'Member2': 'color_hex_value_2', etc... }
        i = 1
        for member_name in participation_values:
            if member_name == member:
                members[str(0)] = member_name
                color_members[member_name] = colors[0]
            else:
                members[str(i)] = member_name
                color_members[member_name] = colors[i]
                i += 1
    else:
        i = 0
        for member_name in participation_values:
            members[str(i)] = member_name
            color_members[member_name] = colors[i]
            i += 1

    total_particip = {'all': 0}
    for member in participation_values:
        total_particip[member] = 0
        for date in labels:
            if date in participation_values[member]:
                particip = participation_values[member][date][metric]
            else:
                particip = 0
            total_particip[member] += particip
            total_particip['all'] += particip
    for member in participation_values:
        participation_values[member]['Average'] = {}
        participation_values[member]['Average'][
            metric] = total_particip[member] / total_particip['all'] * 100

    x = 1
    for date in labels:
        data[date] = {}
        data[date]['date'] = []
        data[date]['x'] = []
        data[date]['y'] = []
        data[date][metric] = []
        data[date]['member'] = []
        data[date]['color'] = []
        for i in range(len(members)):
            member = members[str(i)]
            if date in participation_values[member]:
                particip = participation_values[member][date][metric]
            else:
                particip = 0
            data[date]['color'].append(color_members[member])
            data[date]['date'].append(date)
            data[date]['x'].append(x)
            data[date][metric].append(particip)
            data[date]['y'].append(bottoms[date] + particip / 2)
            data[date]['member'].append(member)
            bottoms[date] += particip
        x += 1

    src_all = {}
    for date in data:
        src_all[date] = ColumnDataSource(data=data[date])

    source_p_values = ColumnDataSource(data=participation_values)
    source_colors = ColumnDataSource(data=color_members)
    source_members = ColumnDataSource(data=members)
    source_labels = ColumnDataSource(data=dict(labels=labels[:-2]))

    height = 500
    width = 800

    if metric == 'turns':
        hover = HoverTool(tooltips="""
                <div>
                <div>
                <span style="font-size: 17px; font-weight: bold;">@member</span>
                </div>
                <div>
                <span style="font-size: 17px;">Date: </span>
                <span style="font-size: 17px; color: purple;">@date</span>
                </div>
                <div>
                <span style="font-size: 17px; font-weight: bold; color: green;">@turns%</span>
                <span style="font-size: 17px;"> Speaking Turns</span>
                </div>
                </div>
            """)

        p = figure(
            title=
            'Your Percentage of Participation (Based on Number of Speaking Turns)',
            plot_width=width,
            plot_height=height,
            x_range=[0.5, len(labels) + 0.5],
            y_range=[-7, 101],
            tools=[hover],
            toolbar_location='above',
            sizing_mode='scale_width')
        p.yaxis.axis_label = 'Your Percentage of Participation (Speaking Turns)'

    elif metric == 'speak':
        hover = HoverTool(tooltips="""
                <div>
                <div>
                <span style="font-size: 17px; font-weight: bold;">@member</span>
                </div>
                <div>
                <span style="font-size: 17px;">Date: </span>
                <span style="font-size: 17px; color: purple;">@date</span>
                </div>
                <div>
                <span style="font-size: 17px; font-weight: bold; color: green;">@speak%</span>
                <span style="font-size: 17px;"> Speaking Time</span>
                </div>
                </div>
            """)

        p = figure(
            title=
            'Your Percentage of Participation (Based on Amount of Speaking Time)',
            plot_width=width,
            plot_height=height,
            x_range=[0.5, len(labels) + 0.5],
            y_range=[-15, 101],
            tools=[hover],
            toolbar_location='above',
            sizing_mode='scale_width')
        p.yaxis.axis_label = 'Your Percentage of Participation (Speaking Time)'

    legends = []
    rects = []
    texts = []
    dates = data.keys()
    dates.sort()
    rect_avg = None
    for date in dates:
        rec = p.rect(source=src_all[date],
                     width=.8,
                     height=metric,
                     x='x',
                     y='y',
                     fill_color='color',
                     line_color='white')
        txt = p.text(
            source=ColumnDataSource(data={
                'date': [data[date]['date'][0]],
                'x': [data[date]['x'][0]]
            }),
            text='date',
            x='x',
            y=-8,
            text_align='center',
            angle=.785)  # radians
        if date == 'Average':
            rect_avg = rec
        else:
            if date != '':
                rects.append(rec)
                texts.append(txt)

    # For legend
    for member in color_members:
        sq = p.square(110, 110, size=0, color=color_members[member])
        legends.append((member, [sq]))

    p.grid.grid_line_alpha = 0.4

    label_font_style = 'normal'  # 'italic', 'bold'
    p.xaxis.axis_label = 'Date'
    p.xaxis.axis_label_text_font_size = str(height / 50) + 'pt'
    p.xaxis.major_label_text_font_size = '0pt'
    p.xaxis.axis_label_text_font_style = label_font_style
    p.xaxis.ticker = FixedTicker(ticks=[0])

    p.yaxis.major_label_text_font_size = str(height / 50) + 'pt'
    p.yaxis.axis_label_text_font_size = str(height / 50) + 'pt'
    p.yaxis.axis_label_text_font_style = label_font_style

    legend = Legend(legends=legends, location=(0, -30))

    p.add_layout(legend, 'right')

    if choose:
        date_pickers = []
        for i in range(len(labels) - 2):
            source_i = ColumnDataSource(data={'i': [i]})
            if metric == 'turns':
                cb = CustomJS(args={
                    'source_p_values': source_p_values,
                    'source_colors': source_colors,
                    'source_labels': source_labels,
                    'source_members': source_members,
                    'txt_source': texts[i].data_source,
                    'source_i': source_i,
                    'r_source_avg': rect_avg.data_source,
                    'r_source': rects[i].data_source
                },
                              code="""
                    var d = cb_obj.get('value');
                    var dMs = Date.parse(d);
                    var dt = new Date(dMs);
                    var day = dt.getDate();
                    day_str = day.toString();
                    if (day < 10){
                      day_str = '0' + day.toString();
                    };
                    var month = dt.getMonth() + 1;  // Month is 1 less than actual picked month for some reason
                    console.log(month);
                    month_str = month.toString();
                    if (month < 10) {
                      month_str = '0' + month.toString();
                    };
                    var date_str = month_str + '/' + day_str;

                    var labels_data = source_labels.get('data');
                    var i = source_i.get('data')['i'][0];
                    labels_data['labels'].splice(i, 1, date_str);
                    var labels = labels_data['labels'];
                    console.log(labels);
                    var p_data = source_p_values.get('data');


                    var total_turns = {'all': 0};
                    for (member in p_data) {
                        total_turns[member] = 0;
                        for (index in labels) {
                            var turns = 0;
                            var date = labels[index];
                            console.log(p_data[member]);
                            if (date in p_data[member]) {
                                turns = p_data[member][date]['turns'];
                            }
                            console.log(turns);
                            total_turns[member] += turns;
                            total_turns['all'] += turns;
                            console.log(total_turns[member]);
                            console.log(total_turns['all']);
                        }
                    }
                    for (member in p_data) {
                        p_data[member]['Average'] = {};
                        console.log(total_turns[member]);
                        p_data[member]['Average']['turns'] = total_turns[member] / total_turns['all'] * 100;
                    }

                    var colors = source_colors.get('data');
                    var members = source_members.get('data');
                    new_data = {}
                    bottom = 0
                    new_data['date'] = []
                    new_data['y'] = []
                    new_data['turns'] = []
                    new_data['member'] = []
                    new_data['color'] = []
                    for (i=0; i<Object.keys(members).length; i++){
                        member = members[i.toString()];
                        var turns = 0;
                        if (date_str in p_data[member]) {
                            turns = p_data[member][date_str]['turns'];
                        };
                        new_data['color'].push(colors[member]);
                        new_data['date'].push(date_str);
                        new_data['turns'].push(turns);
                        new_data['y'].push(bottom + turns/2);
                        new_data['member'].push(member);
                        bottom += turns;
                    }

                    new_avg_data = {}
                    bottom = 0
                    new_avg_data['date'] = []
                    new_avg_data['y'] = []
                    new_avg_data['turns'] = []
                    new_avg_data['member'] = []
                    new_avg_data['color'] = []
                    for (i=0; i<Object.keys(members).length; i++){
                        member = members[i.toString()];
                        turns = p_data[member]['Average']['turns'];
                        new_avg_data['color'].push(colors[member]);
                        new_avg_data['date'].push('Average');
                        new_avg_data['turns'].push(turns);
                        new_avg_data['y'].push(bottom + turns/2);
                        new_avg_data['member'].push(member);
                        bottom += turns;
                    }

                    var r_data = r_source.get('data');
                    var r_avg_data = r_source_avg.get('data');
                    var txt_data = txt_source.get('data');
                    for (key in new_data) {
                        r_data[key] = new_data[key];
                        txt_data[key] = new_data[key];
                        r_avg_data[key] = new_avg_data[key];
                    }
                    console.log(r_avg_data);
                    r_source.trigger('change');
                    r_source_avg.trigger('change');
                    txt_source.trigger('change');
                    """)
            elif metric == 'speak':
                cb = CustomJS(args={
                    'source_p_values': source_p_values,
                    'source_colors': source_colors,
                    'source_labels': source_labels,
                    'source_members': source_members,
                    'txt_source': texts[i].data_source,
                    'source_i': source_i,
                    'r_source_avg': rect_avg.data_source,
                    'r_source': rects[i].data_source
                },
                              code="""
                    var d = cb_obj.get('value');
                    var dMs = Date.parse(d);
                    var dt = new Date(dMs);
                    var day = dt.getDate();
                    day_str = day.toString();
                    if (day < 10){
                      day_str = '0' + day.toString();
                    };
                    var month = dt.getMonth() + 1;  // Month is 1 less than actual picked month for some reason
                    console.log(month);
                    month_str = month.toString();
                    if (month < 10) {
                      month_str = '0' + month.toString();
                    };
                    var date_str = month_str + '/' + day_str;

                    var labels_data = source_labels.get('data');
                    var i = source_i.get('data')['i'][0];
                    labels_data['labels'].splice(i, 1, date_str);
                    var labels = labels_data['labels'];
                    console.log(labels);
                    var p_data = source_p_values.get('data');


                    var total_turns = {'all': 0};
                    for (member in p_data) {
                        total_turns[member] = 0;
                        for (index in labels) {
                            var turns = 0;
                            var date = labels[index];
                            console.log(p_data[member]);
                            if (date in p_data[member]) {
                                turns = p_data[member][date]['speak'];
                            }
                            console.log(turns);
                            total_turns[member] += turns;
                            total_turns['all'] += turns;
                            console.log(total_turns[member]);
                            console.log(total_turns['all']);
                        }
                    }
                    for (member in p_data) {
                        p_data[member]['Average'] = {};
                        console.log(total_turns[member]);
                        p_data[member]['Average']['speak'] = total_turns[member] / total_turns['all'] * 100;
                    }

                    var colors = source_colors.get('data');
                    var members = source_members.get('data');
                    new_data = {}
                    bottom = 0
                    new_data['date'] = []
                    new_data['y'] = []
                    new_data['speak'] = []
                    new_data['member'] = []
                    new_data['color'] = []
                    for (i=0; i<Object.keys(members).length; i++){
                        member = members[i.toString()];
                        var turns = 0;
                        if (date_str in p_data[member]) {
                            turns = p_data[member][date_str]['speak'];
                        };
                        new_data['color'].push(colors[member]);
                        new_data['date'].push(date_str);
                        new_data['speak'].push(turns);
                        new_data['y'].push(bottom + turns/2);
                        new_data['member'].push(member);
                        bottom += turns;
                    }

                    new_avg_data = {}
                    bottom = 0
                    new_avg_data['date'] = []
                    new_avg_data['y'] = []
                    new_avg_data['speak'] = []
                    new_avg_data['member'] = []
                    new_avg_data['color'] = []
                    for (i=0; i<Object.keys(members).length; i++){
                        member = members[i.toString()];
                        turns = p_data[member]['Average']['speak'];
                        new_avg_data['color'].push(colors[member]);
                        new_avg_data['date'].push('Average');
                        new_avg_data['speak'].push(turns);
                        new_avg_data['y'].push(bottom + turns/2);
                        new_avg_data['member'].push(member);
                        bottom += turns;
                    }

                    var r_data = r_source.get('data');
                    var r_avg_data = r_source_avg.get('data');
                    var txt_data = txt_source.get('data');
                    for (key in new_data) {
                        r_data[key] = new_data[key];
                        txt_data[key] = new_data[key];
                        r_avg_data[key] = new_avg_data[key];
                    }
                    console.log(r_avg_data);
                    r_source.trigger('change');
                    r_source_avg.trigger('change');
                    txt_source.trigger('change');
                    """)

            m = int(labels[i].split('/')[0])
            d = int(labels[i].split('/')[1])
            date_pickers.append(
                DatePicker(title='Day ' + str(i + 1),
                           min_date=datetime.datetime(2016, 6, 1),
                           max_date=datetime.datetime.now(),
                           value=datetime.datetime(
                               datetime.datetime.now().year, m, d),
                           callback=cb,
                           width=width / 5,
                           height=200))
        return column(children=[p, row(children=date_pickers)],
                      sizing_mode='scale_width')

    else:
        return p
def product_reviews_over_time_tab(dataset, metadata):

    heading_div = Div(
        text="""<br><h3 style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0.5rem; font-family: &quot;Nunito Sans&quot;, -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; font-weight: 600; color: rgb(26, 26, 26); font-size: 2rem; text-transform: uppercase; letter-spacing: 3px;">Product Review Timeline</h3><pre>Search a product & visualize its Yearly, Monthly, & Daily review trends. Checkout "Product Reviews Timeline - WITH SLIDER (WIP)" tab for the eventual stage of this vis.</pre><hr>""",
        width=1000, height=120, style={'text-align': 'center'})

    combined_data = dataset.set_index('asin').join(metadata.set_index('Product ID')).reset_index()
    combined_data.columns = ['asin', 'reviewerID', 'overall', 'unixReviewTime', 'Description', 'price', 'Category']
    combined_data['asin'] = combined_data['asin'].astype(str)

    def get_product_data(product_id):
        product_data = combined_data[combined_data['asin'] == product_id]

        product_data['dtReviewTime'] = pd.to_datetime(product_data['unixReviewTime'], unit='s')
        product_data['reviewYear'] = product_data['dtReviewTime'].dt.strftime('%Y')
        product_data['reviewMonth'] = product_data['dtReviewTime'].dt.strftime('%Y-%m')
        product_data['dtReviewTime'] = product_data['dtReviewTime'].dt.strftime('%Y-%m-%d')
        product_data = product_data.sort_values('dtReviewTime')
        return product_data

    top_k = 8 if len(combined_data) > 8 else len(combined_data)

    # Default selected_product is the most_purchased_product
    selected_product = combined_data.asin.value_counts().keys()[top_k-1]
    filtered_data = get_product_data(selected_product)
    selected_category = filtered_data.head(1).Category.values[0]

    top_k_products = combined_data.asin.value_counts().head(top_k).keys().tolist()
    bottom_k_products = combined_data.asin.value_counts().sort_values(ascending=True).head(top_k).keys().tolist()

    product_details = dict()
    product_details['asin'] = filtered_data.head(1).asin.values[0]
    product_details['description'] = filtered_data.head(1).Description.values[0]
    product_details['category'] = filtered_data.head(1).Category.values[0]
    review_avg = filtered_data.groupby('Category')['overall'].agg(['mean', 'count']).reset_index()
    product_details['total_reviews'] = str(review_avg['count'].values[0])
    product_details['review_avg'] = str(review_avg['mean'].values[0])
    price_avg = filtered_data.groupby('Category')['price'].agg(['mean', 'count']).reset_index()
    product_details['price_avg'] = str(price_avg['mean'].values[0])

    year_wise_reviews = filtered_data.groupby('reviewYear')['overall'].agg(['mean', 'count']).reset_index()
    year_wise_reviews.columns = ['time', 'average', 'total']

    month_wise_reviews = filtered_data.groupby('reviewMonth')['overall'].agg(['mean', 'count']).reset_index()
    month_wise_reviews.columns = ['time', 'average', 'total']

    date_wise_reviews = filtered_data.groupby('dtReviewTime')['overall'].agg(['mean', 'count']).reset_index()
    date_wise_reviews.columns = ['time', 'average', 'total']

    # Default plot is Year Wise Reviews
    plot_data = year_wise_reviews
    source = ColumnDataSource(
        data=dict(
            time_stamp=list(map(str, plot_data['time'])),
            total=plot_data.total.tolist(),
            average=plot_data.average.tolist(),
            color=getKColors(len(plot_data))))

    # Adding hover tool
    hover = HoverTool(tooltips=[('Time', '@time_stamp'),
                                ('Avg Review', '@average'),
                                ('Total Reviews', '@total')],
                      mode='vline')

    # Total Reviews Figure
    p1 = figure(x_range=plot_data.time.tolist(), plot_width=1200, plot_height=300)
    r1_l = p1.line(source=source, x='time_stamp', y='total', line_width=2)
    r1_c = p1.circle(source=source, x='time_stamp', y='total', size=15, color="red", alpha=0.5)

    p1.add_tools(hover)

    # Formatting axes
    p1.xaxis.axis_label = ""
    p1.xaxis.major_label_orientation = math.pi / 2
    p1.xaxis.major_label_text_font_size = "10pt"
    p1.xaxis.axis_label_text_font_size = "0pt"

    p1.yaxis.axis_label = "Total Reviews"
    p1.yaxis.formatter = NumeralTickFormatter(format="0")
    p1.yaxis.major_label_text_font_size = "10pt"
    p1.yaxis.axis_label_text_font_size = "15pt"

    ds1_l = r1_l.data_source
    ds1_c = r1_c.data_source

    # Average Rating Figure
    p2 = figure(x_range=plot_data.time.tolist(), plot_width=1200, plot_height=300)
    r2_l = p2.line(source=source, x='time_stamp', y='average', line_width=2)
    r2_c = p2.circle(source=source, x='time_stamp', y='average', size=15, color="red", alpha=0.5)

    p2.add_tools(hover)

    # Formatting axes
    p2.xaxis.axis_label = "Time"
    p2.xaxis.major_label_orientation = math.pi / 2
    p2.xaxis.major_label_text_font_size = "10pt"
    p2.xaxis.axis_label_text_font_size = "15pt"

    p2.yaxis.axis_label = "Average Rating"
    p2.yaxis.formatter = NumeralTickFormatter(format="0")
    p2.yaxis.major_label_text_font_size = "10pt"
    p2.yaxis.axis_label_text_font_size = "15pt"

    ds2_l = r2_l.data_source
    ds2_c = r2_c.data_source

    radio_button_group = RadioButtonGroup(
        labels=["Yearly", "Monthly", "Daily"], active=0, width=1200)

    def get_updated_plot_data_dict(new_plot_data):

        new_data = dict()

        if new_plot_data.empty:
            new_data['x_range'] = []
            new_data['time_stamp'] = []
            new_data['average'] = []
            new_data['total'] = []
            new_data['color'] = []

        else:
            new_colors = getKColors(len(new_plot_data))

            new_data['x_range'] = new_plot_data.time.tolist()
            new_data['time_stamp'] = new_plot_data.time.tolist()
            new_data['average'] = new_plot_data.average.tolist()
            new_data['total'] = new_plot_data.total.tolist()
            new_data['color'] = new_colors

        return new_data

    def update_plot(attr, old, new):

        global year_wise_reviews, month_wise_reviews, date_wise_reviews, filtered_data, selected_product

        try:
            selected_product
        except NameError:
            selected_product = combined_data.asin.value_counts().head(1).index[0]

        filtered_data = get_product_data(selected_product)

        new_plot_data = plot_data

        if radio_button_group.active == 0:
            try:
                year_wise_reviews
            except NameError:
                year_wise_reviews = None

            year_wise_reviews = filtered_data.groupby('reviewYear')['overall'].agg(['mean', 'count']).reset_index()
            year_wise_reviews.columns = ['time', 'average', 'total']

            new_plot_data = year_wise_reviews

        if radio_button_group.active == 1:

            try:
                month_wise_reviews
            except NameError:
                month_wise_reviews = None

            month_wise_reviews = filtered_data.groupby('reviewMonth')['overall'].agg(
                ['mean', 'count']).reset_index()
            month_wise_reviews.columns = ['time', 'average', 'total']
            new_plot_data = month_wise_reviews

        if radio_button_group.active == 2:

            try:
                date_wise_reviews
            except NameError:
                date_wise_reviews = None

            date_wise_reviews = filtered_data.groupby('dtReviewTime')['overall'].agg(
                ['mean', 'count']).reset_index()
            date_wise_reviews.columns = ['time', 'average', 'total']
            new_plot_data = date_wise_reviews

        new_data = get_updated_plot_data_dict(new_plot_data)

        p1.x_range.factors = new_data['x_range']
        p2.x_range.factors = new_data['x_range']

        ds1_l.data = new_data
        ds1_c.data = new_data
        ds2_l.data = new_data
        ds2_c.data = new_data

    radio_button_group.on_change('active', update_plot)

    def generate_div_text(product_attributes):
        return """<table width="1200px" style='font-family: arial, sans-serif; border-collapse: collapse; width: 100%;'> 
                                        <tr> 
                                            <th style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center;'>Attribute</th> 
                                            <th style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center;'>Value</th> </tr>

                                        <tr> 
                                            <td style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center; background-color: #dddddd'>
                                                Product ID
                                            </td>
                                            <td style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center; background-color: #dddddd'>
                                                """ + product_attributes['asin'] + """
                                            </td>
                                        </tr>

                                        <tr> 
                                            <td style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center;'>
                                                Description
                                            </td>
                                            <td style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center'>
                                                """ + product_attributes['description'] + """
                                            </td>
                                        </tr>

                                        <tr> 
                                            <td style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center; background-color: #dddddd'>
                                                Category
                                            </td>
                                            <td style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center; background-color: #dddddd'>
                                                """ + product_attributes['category'] + """
                                            </td>
                                        </tr>

                                        <tr> 
                                            <td style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center;'>
                                                Total Reviews
                                            </td>
                                            <td style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center'>
                                                """ + str(product_attributes['total_reviews']) + """
                                            </td>
                                        </tr>

                                        <tr> 
                                            <td style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center; background-color: #dddddd'>
                                                Average Rating
                                            </td>
                                            <td style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center; background-color: #dddddd'>
                                                """ + str(product_attributes['review_avg']) + """
                                            </td>
                                        </tr>

                                        <tr> 
                                            <td style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center;'>
                                                Average Price
                                            </td>
                                            <td style='border: 1px solid #dddddd; text-align: left; padding: 8px; align: center'>
                                                """ + str(product_attributes['price_avg']) + """
                                            </td>
                                        </tr>

                                        </table>"""

    product_details_div = Div(text=generate_div_text(product_details), width=1200, height=300)

    def update_selection():

        if not search_input.value:
            return

        global year_wise_reviews, month_wise_reviews, date_wise_reviews, product_details, filtered_data, selected_product
        selected_product = search_input.value
        searched_data = get_product_data(search_input.value)
        filtered_data = searched_data
        new_data = dict()

        if searched_data.empty:

            year_wise_reviews = searched_data
            month_wise_reviews = searched_data
            date_wise_reviews = searched_data

            new_data['x_range'] = []
            new_data['time_stamp'] = []
            new_data['average'] = []
            new_data['total'] = []
            new_data['color'] = []

            p1.x_range.factors = new_data['x_range']
            p2.x_range.factors = new_data['x_range']

            product_details_div.text = """<img alt="Sorry! No product found." src="/myapp/static/images/no_results_found.png">"""

        else:

            product_details = dict()

            product_details['asin'] = searched_data.head(1).asin.values[0]
            product_details['description'] = searched_data.head(1).Description.values[0]
            product_details['category'] = searched_data.head(1).Category.values[0]
            updated_review_avg = searched_data.groupby('Category')['overall'].agg(['mean', 'count']).reset_index()
            product_details['total_reviews'] = str(updated_review_avg['count'].values[0])
            product_details['review_avg'] = str(updated_review_avg['mean'].values[0])
            updated_price_avg = searched_data.groupby('Category')['price'].agg(['mean', 'count']).reset_index()
            product_details['price_avg'] = str(updated_price_avg['mean'].values[0])

            product_details_div.text = generate_div_text(product_details)

            year_wise_reviews = searched_data.groupby('reviewYear')['overall'].agg(['mean', 'count']).reset_index()
            year_wise_reviews.columns = ['time', 'average', 'total']

            month_wise_reviews = searched_data.groupby('reviewMonth')['overall'].agg(['mean', 'count']).reset_index()
            month_wise_reviews.columns = ['time', 'average', 'total']

            date_wise_reviews = searched_data.groupby('dtReviewTime')['overall'].agg(['mean', 'count']).reset_index()
            date_wise_reviews.columns = ['time', 'average', 'total']

            if radio_button_group.active == 0:
                new_plot_data = year_wise_reviews
            if radio_button_group.active == 1:
                new_plot_data = month_wise_reviews
            if radio_button_group.active == 2:
                new_plot_data = date_wise_reviews

            new_data = get_updated_plot_data_dict(new_plot_data)

            p1.x_range.factors = new_data['x_range']
            p2.x_range.factors = new_data['x_range']

        ds1_l.data = new_data
        ds1_c.data = new_data
        ds2_l.data = new_data
        ds2_c.data = new_data

    search_input = TextInput(value=selected_product, title="Product ID:")
    search_button = Button(label="Search by Product Id", button_type="success")
    search_button.on_click(update_selection)

    search_category_input = TextInput(value=selected_category, title="Category:")
    search_category_button = Button(label="Search by Category", button_type="primary")

    def get_div_text_for_category():

        global selected_category
        selected_category = search_category_input.value

        category_data = combined_data[combined_data['Category'].str.lower() == str(search_category_input.value).lower()]

        if category_data.empty:

            return """<font size="4"><b>Sorry! No products found for <mark><u>\"""" + selected_category + """\"</u></mark> category.</b></font> <br><br>"""

        top_k_category = 8 if len(category_data) > 8 else len(category_data)
        top_k_category_products = category_data.asin.value_counts().head(top_k_category).keys().tolist()
        bottom_k_category_products = category_data.asin.value_counts().sort_values(ascending=True).head(top_k_category).keys().tolist()

        top_k_category_pid_list = ""
        temp_category_count = 1
        for j in range(len(top_k_category_products)):
            if temp_category_count % 4 == 0:
                top_k_category_pid_list += top_k_category_products[j] + """<br>"""
                temp_category_count = 0
            else:
                top_k_category_pid_list += top_k_category_products[j] + ", "

            temp_category_count = temp_category_count + 1

        bottom_k_category_pid_list = ""
        temp_category_count = 1
        for j in range(len(bottom_k_category_products)):
            if temp_category_count % 4 == 0:
                bottom_k_category_pid_list += bottom_k_category_products[j] + """<br>"""
                temp_category_count = 0
            else:
                bottom_k_category_pid_list += bottom_k_category_products[j] + ", "

            temp_category_count = temp_category_count + 1

        text_data = """<font size="4"><b>Top & Worst performers for <mark><u>\"""" + selected_category + """\"</u></mark> category:</b></font> <br><br>""" + \
                    """<font color="blue" size="3"><b>Top """ + str(top_k_category) + """ products:</b></font><br>""" + \
                    top_k_category_pid_list + """<br>""" + \
                    """<font color="red" size="3"><b>Bottom """ + str(top_k_category) + """ products:</b></font><br>""" + \
                    bottom_k_category_pid_list
        return text_data

    def init_div_text_for_category():

        category_data = combined_data[combined_data['Category'].str.lower() == str(search_category_input.value).lower()]
        top_k_category = 8 if len(category_data) > 8 else len(category_data)
        top_k_category_products = category_data.asin.value_counts().head(top_k_category).keys().tolist()
        bottom_k_category_products = category_data.asin.value_counts().sort_values(ascending=True).head(top_k_category).keys().tolist()

        top_k_category_pid_list = ""
        temp_category_count = 1
        for j in range(len(top_k_category_products)):
            if temp_category_count % 4 == 0:
                top_k_category_pid_list += top_k_category_products[j] + """<br>"""
                temp_category_count = 0
            else:
                top_k_category_pid_list += top_k_category_products[j] + ", "

            temp_category_count = temp_category_count + 1

        bottom_k_category_pid_list = ""
        temp_category_count = 1
        for j in range(len(bottom_k_category_products)):
            if temp_category_count % 4 == 0:
                bottom_k_category_pid_list += bottom_k_category_products[j] + """<br>"""
                temp_category_count = 0
            else:
                bottom_k_category_pid_list += bottom_k_category_products[j] + ", "

            temp_category_count = temp_category_count + 1

        text_data = """<font size="4"><b>Top and Worst performers for <mark><u>\"""" + selected_category + """\"</u></mark> category:</b></font> <br><br>""" + \
                    """<font color="blue" size="3"><b>Top """ + str(top_k_category) + """ products:</b></font><br>""" + \
                    top_k_category_pid_list + """<br>""" + \
                    """<font color="red" size="3"><b>Bottom """ + str(top_k_category) + """ products:</b></font><br>""" + \
                    bottom_k_category_pid_list
        return text_data

    sample_pid_for_category_div = Div(text=init_div_text_for_category(), width=450, height=130)

    def update_category_div():
        if not search_category_input.value:
            return
        sample_pid_for_category_div.text = get_div_text_for_category()

    search_category_button.on_click(update_category_div)

    top_k_pid_list = ""
    temp_count = 1
    for i in range(len(top_k_products)):
        # top_k_pid_list += top_k_products[i] + ", "
        if temp_count % 4 == 0:
            top_k_pid_list += top_k_products[i] + """<br>"""
            temp_count = 0
        else:
            top_k_pid_list += top_k_products[i] + ", "

        temp_count = temp_count + 1

    bottom_k_pid_list = ""
    temp_count = 1
    for i in range(len(bottom_k_products)):
        # bottom_k_pid_list += bottom_k_products[i] + ", "
        if temp_count % 4 == 0:
            bottom_k_pid_list += bottom_k_products[i] + """<br>"""
            temp_count = 0
        else:
            bottom_k_pid_list += bottom_k_products[i] + ", "

        temp_count = temp_count + 1

    pre_text_data = """<font size="4"><b><u>Overall</u> Top & Worst performers:</b></font> <br><br>""" + \
                    """<font color="blue" size="3"><b>Top """ + str(top_k) + """ :</b></font><br>""" + \
                    top_k_pid_list + """<br>""" + \
                    """<font color="red" size="3"><b>Bottom """ + str(top_k) + """ :</b></font><br>""" + \
                    bottom_k_pid_list
    sample_product_ids = Div(text=pre_text_data, width=450, height=130)

    # layout = column(search_input, search_button, product_details_div, radio_button_group, p1, p2)
    layout = column(heading_div,
                    row(column(search_category_input, search_category_button, sample_pid_for_category_div),
                        column(search_input, search_button, sample_product_ids),
                        product_details_div),
                    radio_button_group, p1, p2)
    tab = Panel(child=layout, title='Product Reviews Timeline')
    return tab
示例#11
0
    }
    # Assign new_data to source.data
    source.data = new_data

    # Add title to plot
    plot.title.text = 'Stock data for %s' % yr


# Create a dropdown slider widget: slider
slider = Slider(start=2013, end=2018, step=1, value=2013, title='Year')

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

# Create a dropdown Select widget for the x data: x_select
y_select = Select(options=['Close', 'High', 'Open', 'Low'],
                  value='Open',
                  title='y-axis data')

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

#Creating a HoverTool
hover = HoverTool(tooltips=[('Price', '@y'), ('Date', '@x')])

plot.add_tools(hover)

# Create layout and add to current document
layout = row(widgetbox(slider, y_select), plot)
curdoc().add_root(layout)
示例#12
0
               options=open(join(dirname(__file__),
                                 'genres.txt')).read().split())
director = TextInput(title="Director name contains")
cast = TextInput(title="Cast names contains")
x_axis = Select(title="X Axis",
                options=sorted(axis_map.keys()),
                value="Tomato Meter")
y_axis = Select(title="Y Axis",
                options=sorted(axis_map.keys()),
                value="Number of Reviews")

# Create Column Data Source that will be used by the plot
source = ColumnDataSource(
    data=dict(x=[], y=[], color=[], title=[], year=[], revenue=[]))

hover = HoverTool(tooltips=[("Title", "@title"), ("Year",
                                                  "@year"), ("$", "@revenue")])

p = Figure(plot_height=600,
           plot_width=800,
           title="",
           toolbar_location=None,
           tools=[hover])
p.circle(x="x",
         y="y",
         source=source,
         size=7,
         color="color",
         line_color=None,
         fill_alpha="alpha")

def Donut(data,
          label='index',
          values=None,
          color=None,
          agg=None,
          hover_tool=True,
          hover_text=None,
          plot_height=400,
          plot_width=400,
          xgrid=False,
          ygrid=False,
          **kw):
    """ Create a Donut chart containing one or more layers from table-like data.

    Create a donut chart using :class:`DonutBuilder
    <bkcharts.builders.donut_builder.DonutBuilder>` to
    render the glyphs from input data and specification. The primary
    use case for the donut chart is to show relative amount each category, within a
    categorical array or multiple categorical arrays, makes up of the whole for some
    array of values.

    Args:
        data (:ref:`userguide_charts_data_types`): the data source for the chart
            label (str or list(str), optional): the categorical variable to use for
            creating separate boxes
        values (str, optional): the values to use for producing the boxplot using
            table-like input data
        color (str or list(str) or bkcharts._attributes.ColorAttr, optional): the
            categorical variable or color attribute specification to use for coloring
            the wedges
        agg (str, optional): how the values associated with a wedge should be
            aggregated
        hover_tool (bool, optional): whether to show the value of the
            wedge when hovering
        hover_text (str, optional): provide an alternative string to use to label the
            value shown with the hover tool
        **kw:

    In addition to the parameters specific to this chart,
    :ref:`userguide_charts_defaults` are also accepted as keyword parameters.

    Returns:
        :class:`Chart`: includes glyph renderers that generate the wedges the make up
        the donut(s)

    Examples:

    .. bokeh-plot::
        :source-position: above

        from bkcharts import Donut, show, output_file
        from bkcharts.utils import df_from_json
        from bokeh.sampledata.olympics2014 import data

        import pandas as pd

        # utilize utility to make it easy to get json/dict data converted to a dataframe
        df = df_from_json(data)

        # filter by countries with at least one medal and sort by total medals
        df = df[df['total'] > 8]
        df = df.sort_values(by="total", ascending=False)
        df = pd.melt(df, id_vars=['abbr'],
                     value_vars=['bronze', 'silver', 'gold'],
                     value_name='medal_count', var_name='medal')

        # original example
        d = Donut(df, label=['abbr', 'medal'], values='medal_count',
                  text_font_size='8pt', hover_text='medal_count')

        output_file("donut.html")

        show(d)

    """

    kw['label'] = label
    kw['values'] = values
    kw['color'] = color
    kw['xgrid'] = xgrid
    kw['ygrid'] = ygrid
    kw['plot_height'] = plot_height
    kw['plot_width'] = plot_width

    if agg is not None:
        kw['agg'] = agg

    chart = create_and_build(DonutBuilder, data, **kw)

    chart.left[0].visible = False
    chart.below[0].visible = False

    values, agg = derive_aggregation(dim_cols=label, agg_col=values, agg=agg)
    if hover_tool:
        tooltip = build_agg_tooltip(hover_text=hover_text,
                                    aggregated_col=values,
                                    agg_text=agg)
        chart.add_tools(HoverTool(tooltips=[tooltip]))

    return chart
def generate_sentiment_ts_plot(sentiment_ts_data, sentiment_ts_sample_count):
    tooltips = [
        ("Date", "@date{%F}"),
        ("Mentions", "@Count"),
        ("Nett Sentiment (7 day mean)", "@NettSentiment{0.0%}"),
    ]

    line_plot = figure(title=None,
                       width=None,
                       height=None,
                       sizing_mode="scale_both",
                       x_range=(sentiment_ts_data["date"].min(),
                                sentiment_ts_data["date"].max()),
                       x_axis_type='datetime',
                       y_axis_label="Nett Sentiment (7 day mean)",
                       tools=[],
                       toolbar_location=None)
    # Setting range of y range
    line_plot.y_range = Range1d(-1, 1)

    # Adding Count range on the right
    line_plot.extra_y_ranges = {
        "count_range": Range1d(start=0,
                               end=sentiment_ts_sample_count.max() * 1.1)
    }
    secondary_axis = LinearAxis(y_range_name="count_range",
                                axis_label="Mentions")
    line_plot.add_layout(secondary_axis, 'right')

    sentiment_count_bars = line_plot.vbar(x="date",
                                          top="Count",
                                          width=pandas.Timedelta(days=0.75),
                                          color="orange",
                                          source=sentiment_ts_data,
                                          y_range_name="count_range")
    sentiment_line = line_plot.line(x="date",
                                    y="NettSentiment",
                                    color="blue",
                                    source=sentiment_ts_data,
                                    line_width=5)

    # Long Term sentiment baseline
    long_term_sentiment_span = Span(
        location=LONG_TERM_SENTIMENT,
        name="LongTermSentiment",
        dimension='width',
        line_color='red',
        line_dash='dashed',
        line_width=3,
    )
    line_plot.add_layout(long_term_sentiment_span)

    start_timestamp = sentiment_ts_data["date"].min()
    long_term_sentiment_label = Label(x=start_timestamp,
                                      y=LONG_TERM_SENTIMENT,
                                      x_offset=-10,
                                      y_offset=10,
                                      text='Sentiment Baseline',
                                      render_mode='css',
                                      border_line_color='white',
                                      border_line_alpha=0.0,
                                      angle=0,
                                      angle_units='deg',
                                      background_fill_color='white',
                                      background_fill_alpha=0.0,
                                      text_color='red',
                                      text_font_size='12pt')
    line_plot.add_layout(long_term_sentiment_label)

    hover_tool = HoverTool(renderers=[sentiment_line, sentiment_count_bars],
                           tooltips=tooltips,
                           formatters={
                               '@date': 'datetime',
                               'NettSentiment': 'printf'
                           })
    line_plot.add_tools(hover_tool)

    line_plot.xaxis.formatter = DatetimeTickFormatter(days="%Y-%m-%d")
    line_plot.yaxis.formatter = NumeralTickFormatter(format="0.[0]%")
    secondary_axis.formatter = NumeralTickFormatter(format="0.[0] a")

    line_plot.axis.axis_label_text_font_size = "12pt"
    line_plot.axis.major_label_text_font_size = "12pt"

    plot_html = file_html(line_plot, CDN, "Behavioural Sentiment Timeseries")

    return plot_html
def analysis(request):

    df = pd.DataFrame(Expense.objects.values())

    df.drop('id',axis=1,inplace=True)
    df["amount"] = df["amount"].astype(int)
    #sorting on date basis
    df = df.sort_values(by=['date'])
    
    #now I don't need time so remove time from date
    df['date'] = pd.to_datetime(df['date']).dt.date
    df['date'] = pd.to_datetime(df['date'])
    df['datestr'] = df['date'].apply(lambda x: x.strftime('%Y-%m-%d')) 
    #using lambda expressions to convert the date into a string representation

    
    #for months only logic and plotting graph
    dfmonth = df[df['date'] >= datetime.today().replace(day=1)]
    source = ColumnDataSource(dfmonth)
    
    #---------------- for prediction-------------------------
    df.drop(["transaction_name","datestr"],axis=1,inplace = True)
    #lets combine the amount by date
    dfcopy = df.groupby('date').sum()
    # working with days only
    dfcopy['days_from_start'] = (dfcopy.index - dfcopy.index[0]).days
    #calculating remaining balance after each transaction and storing in dataframe
    remaining = []
    eachamount = dfcopy.amount[0]
    remaining.append(dfcopy.amount[0])
    for i in range(len(dfcopy)-1):
        eachamount += dfcopy.amount[i+1]
        remaining.append(eachamount)
    #separating input and targets as
    X = dfcopy["days_from_start"].values
    Y= remaining
    #lets reshape the input
    X = X.reshape([-1,1])
    #use linear regression from sklearn
    model = LinearRegression()
  
    model.fit(X,Y)
    
    print(model.score(X,Y))
    
    ypredicts = model.predict(X)
    #for 10 days prediction
    endindex = len(dfcopy)-1
    days_from_start = dfcopy['days_from_start'][endindex]
    #logic for setting next 7 days input
    nextdate = dfcopy.index[endindex]
    nextdatetime = []
    nextdatedays = []

    for i in range(1,10):
        nextdatedays.append(days_from_start + i)
        nextdate += timedelta(days=1)
        nextdatetime.append(nextdate)
    
    dfpredict = pd.DataFrame({
        'days':nextdatedays,
    })
    
    yfuture = model.predict(dfpredict)
    
    for i in range(len(nextdatetime)):
        nextdatetime[i] = nextdatetime[i].strftime("%Y-%m-%d")
        yfuture[i] = round(yfuture[i])


    #-------------------------prediction done-----------------
    
    #todays month
    month = datetime.today().strftime("%B")
    
    #setup graph plot for displaying monthly income and expense
    plot1 = figure(
        title = month +' Graph',
        x_axis_type='linear',
        x_axis_label = "Days",
        y_axis_label = "Amount",
        plot_width = 1060,
        plot_height = 500,
    )
    plot1.line(x='date',y = 'amount',line_width=1,legend_label="Daily Basis Income And Expense",source=source)
    plot1.circle(x='date',y='amount',fill_color='white',size=8,legend_label="Daily Basis Income And Expense",source=source)
    
    plot1.xaxis.formatter=DatetimeTickFormatter(days="%Y/%m/%d")
   
    plot1.add_tools(HoverTool(tooltips=[
        ("date","@datestr"),
        ('transaction_name',"@transaction_name"),
        ("amount",'@amount')]))
    #store components
    script1,div1 = components(plot1)

    plot2 = figure(
        title = "Remaining Balance Graph using Linear Regression",
        x_axis_type="datetime",
        x_axis_label = "Days",
        y_axis_label ="Amount",
        plot_width = 650,
        plot_height = 500,
    )
    
    #print(dfpredict)
    plot2.line(x=dfcopy.index,y=remaining,line_color="red",line_width=5,legend_label="Actual Data")
    plot2.line(x=dfcopy.index,y=ypredicts,line_color="green",line_width=3,legend_label="predicted Data",line_dash="dotted")
    script2,div2 = components(plot2)
    
    #lets zip for using two variables in jinja
    predict = zip(nextdatetime,yfuture)
    #render to analysis.html
    return render(request,'analysis/analysis.html',{
        'script1':script1,
        'div1':div1,
        'month':month,
        'script2':script2,
        'div2':div2,
        'predict':predict,
    })
示例#16
0
            plot_width=950,
            toolbar_location='above',
            tools="pan, wheel_zoom, box_zoom, reset")

p1.xgrid.grid_line_color = None
p1.ygrid.grid_line_color = None

# Plot the map using patches, set the fill_color as mappers['Density']
cantons = p1.patches(...)

# Create a colorbar with mapper['Density'] and add it to above figure
color_bar = ColorBar(...)
p1.add_layout(color_bar, 'right')

# Add a hovertool to display canton, density, bedspercapita and dnc
hover = HoverTool(tooltips=[...], renderers=[cantons])

p1.add_tools(hover)

# T2.3 Add circles at the locations of capital cities for each canton, and the sizes are proportional to daily new cases per capita
sites = p1.circle(...)

# T2.4 Create a radio button group with labels 'Density', and 'BedsPerCapita'
buttons = RadioButtonGroup(...)


# Define a function to update color mapper used in both patches and colorbar
def update_bar(new):
    for i, d in enumerate(labels):
        if i == new:
            ...
示例#17
0
from bokeh.plotting import figure
from bokeh.io import output_file, show
from bokeh.sampledata.iris import flowers
from bokeh.models import Range1d, PanTool, ResetTool, HoverTool, WheelZoomTool

from PIL import ImageGrab
#from screeninfo import get_monitors

# Define the output file path
output_file("../nb/ch2/iris_ex3sol.html")

# Create the figure object
f = figure(tools=[PanTool(), ResetTool(), WheelZoomTool()])

# Style the tools
hover = HoverTool(tooltips=[("Species", "@species"), ("Sepal Width", "@sepal_width")])
f.add_tools(hover)
f.toolbar_location = 'above'
f.toolbar.logo = None

# Style the plot area
f.plot_width = int(
    ImageGrab.grab().width / 2)  # This will return your monitor width. ImageGrab was imported further above from the PIL library which can be installed with "pip install pillow"
f.plot_height = int(
    ImageGrab.grab().height / 2 - 50)  # This will return your monitor width. ImageGrab was imported further above from the PIL library which can be installed witt "pip install pillow"

#screeninfo impl
#f.plot_width=get_monitors()[0].width #get_monitors is part of the screeninfo module imported above
#f.plot_height=get_monitors()[0].height-50

f.background_fill_color = "grey"
    })

#Creating empty plot
fig = figure(title="Empty plot", tools="pan,wheel_zoom,lasso_select")
p = fig.circle(
    x='axis1',
    y='axis2',
    fill_color='colors',
    source=source,
    fill_alpha=0.8,
    size=10,
    line_alpha=0,
    selection_alpha=1,
    selection_fill_color='colors',
)
fig.add_tools(HoverTool(tooltips=[('Population', '@y')]))

p.nonselection_glyph = None

plot = column(row(fig, column(multiselect, button)),
              row(focus, reset, view3d, download_file))

#functions called on pressing each button
button.on_click(update)

focus.on_click(focus_selected)
reset.on_click(reset_points)
view3d.on_click(project)

download_file.on_click(download)
示例#19
0
output_file("customjs_hover.html")

# range bounds supplied in web mercator coordinates
p = figure(x_range=(-2000000, 6000000), y_range=(-1000000, 7000000),
           x_axis_type="mercator", y_axis_type="mercator")
p.add_tile(get_provider(CARTODBPOSITRON))

p.circle(x=[0, 2000000, 4000000], y=[4000000, 2000000, 0], size=30)

code = """
    const projections = Bokeh.require("core/util/projections");
    const x = special_vars.x
    const y = special_vars.y
    const coords = projections.wgs84_mercator.invert(x, y)
    return coords[%d].toFixed(2)
"""

p.add_tools(HoverTool(
    tooltips=[
        ( 'lon', '$x{custom}' ),
        ( 'lat', '$y{custom}' ),
    ],

    formatters={
        '$x' : CustomJSHover(code=code % 0),
        '$y' : CustomJSHover(code=code % 1),
    }
))

show(p)
示例#20
0
def plot_rolling_alpha(rolling_window,factors_to_plot):
    
    result_array = np.zeros((1,len(factors_to_plot)+1)) # Initializing the results array
    factors1 = factors_to_plot + ['Alpha']
    X = df[factors_to_plot].values
    Y = (df['Daily_Returns']-df[factor_riskfree[0]]).values # Calculating Excess Daily returns by subtracting Risk free returns
    dates = df['Date'].values
    for i in range(X.shape[0]-rolling_window+1): #Loop to do regression for each time period of rolling window
        x = X[i:rolling_window+i] # The X variables for regression based on rolling window
        y = Y[i:rolling_window+i] # The Y variable for regression based on rolling window
        regressor = LinearRegression().fit(x, y) # Doing the linear regression
        temp = np.append(regressor.coef_,regressor.intercept_) # Constructing the results of the regression numpy arrray by appending the alpha to the betas
        result_array = np.vstack((result_array, np.resize(temp,(1,len(factors_to_plot)+1)))) # Appending the Results of regression to result_array

    result_array = np.delete(result_array, 0, 0) # Deleing the first initialized row of the result_array
    dates = dates[rolling_window-1:] # Determing the dates of all the days on which rolling window regression is done
    result_alpha = pd.DataFrame(result_array, index=dates) # Values are not rounded to make the plots of annual alpha
    result_alpha.columns = factors1
    
    # To insert date column in the result_df dataframe
    df3 = pd.DataFrame(data=list(dates), columns=['int_date'])
    df3[['str_date']] = df3[['int_date']].applymap(str).applymap(lambda s: "{}-{}-{}".format(s[0:4], s[4:6], s[6:] ))
    rolling_dates=list(df3['str_date'])
    # df[['str_date']] = df[['int_date']].applymap(str).applymap(lambda s: "{}/{}/{}".format(s[6:], s[4:6], s[0:4]))
    dates = np.array(rolling_dates, dtype=np.datetime64)
    rolling_ndays = len(dates)
    
    source = ColumnDataSource(data=dict(date=dates, close=list(result_alpha['Alpha'].values*256)))
    mypalette=Spectral11[:4]+Spectral11[8:] 

    p = figure(title = f'Rolling Annual %Alpha: {rolling_window} days window - Betas: {factors_to_plot}', plot_height=550, plot_width=1500, 
               toolbar_location='above', x_axis_type="datetime", x_axis_location="above", background_fill_color="#efefef", 
               x_range=(dates[(ndays-rolling_window)//3], dates[((ndays-rolling_window)*2)//3])) #, tools="xpan" ,tooltips=tooltips,
    p.toolbar.logo = None
    p.line('date', 'close', source=source,line_width=3, legend_label="% ALPHA", name="% ALPHA", color=mypalette[0])
    p.legend.background_fill_alpha = 0
    p.yaxis.axis_label = '%age Returns'

    p.yaxis.axis_label_text_font_size= "18px"
    p.axis.major_label_text_font_size = '16px'
    p.legend.label_text_font_size = '16px'

    hover_tool1 = HoverTool(
        tooltips=[
            ( 'Date',   '$x{%F}'),
            ( 'ALPHA',  '@close%' ) # use @{ } for field names with spaces @{% ALPHA}
        ],
        formatters={
            '$x':'datetime', # use 'datetime' formatter for '@date' field
        },
        names = ["% ALPHA"],
        mode='vline' # display a tooltip whenever the cursor is vertically in line with a glyph
    )
    p.tools.append(hover_tool1)

    p.title.text_color = mypalette[-1]
    p.title.text_alpha = 0.6
    p.title.text_font = "antiqua"
    p.title.text_font_size = "22px"
    p.title.align = "center"

    select = figure(title="Drag the middle and edges of the selection box to change the range above",
                    plot_height=140, plot_width=1500, y_range=p.y_range,
                    x_axis_type="datetime", y_axis_type=None,
                    tools="", toolbar_location=None, background_fill_color="#efefef")

    range_tool = RangeTool(x_range=p.x_range)
    range_tool.overlay.fill_color = "navy"
    range_tool.overlay.fill_alpha = 0.2

    select.line('date', 'close', source=source, color=mypalette[0])
    select.ygrid.grid_line_color = None
    select.add_tools(range_tool)
    select.toolbar.active_multi = range_tool
#     rolling_alpha = file_html([p,select], CDN)
    return column(p,select)
示例#21
0
def makeplot_2(df, FC_P, PV_P, Inhibitor):

    df = df[df['Kinase'] != '']  # Drop of data with no Kinase allocated

    df.loc[(df['Fold_Change_Cal'] > FC_P) & (df['p_value'] < PV_P),
           'color'] = "Blue"  # upregulated
    # df.loc - Selects single row or subset of rows from the DataFrame by label
    df.loc[(df['Fold_Change_Cal'] <= FC_P) & (df['p_value'] < PV_P),
           'color'] = "Purple"  # downregulated
    df['color'].fillna('grey', inplace=True)

    df["log_pvalue"] = -np.log10(df['p_value'])
    df["log_FC"] = np.log2(df['Fold_Change_Cal'])

    df.head()

    output_notebook()

    category = 'Substrate'

    category_items = df[category].unique()

    title = Inhibitor + " :Data with identified kinases"
    #feeding data into ColumnDataSource
    source = ColumnDataSource(df)
    #Editing the hover that need to displayed while hovering
    hover = HoverTool(tooltips=[
        ('Kinase', '@Kinase'),
        ('Substrate', '@Substrate'),
        ('Sub_gene', '@Sub_gene'),
        ('Phosphosite', '@Phosphosite'),
        ('Fold_Change_Cal', '@Fold_Change_Cal'),  #C7
        ('p_value', '@p_value')
    ])
    #tools that are need to explote data
    tools = [
        hover,
        WheelZoomTool(),
        PanTool(),
        BoxZoomTool(),
        ResetTool(),
        SaveTool()
    ]

    #finally making figure with scatter plot
    pp = figure(tools=tools,
                title=title,
                plot_width=700,
                plot_height=600,
                toolbar_location='right',
                toolbar_sticky=False,
                x_axis_label='Log2 Fold Change',
                y_axis_label='Log10 p-value')

    pp.scatter(x='log_FC',
               y='log_pvalue',
               source=source,
               size=10,
               color='color')

    #displaying the graph
    return (pp)
示例#22
0
def plot_rolling_beta(rolling_window,factors_to_plot):
    
    result_array = np.zeros((1,len(factors_to_plot)+1)) # Initializing the results array
    factors1 = factors_to_plot + ['Alpha']
    X = df[factors_to_plot].values
    Y = (df['Daily_Returns']-df[factor_riskfree[0]]).values # Calculating Excess Daily returns by subtracting Risk free returns
    dates = df['Date'].values
    for i in range(X.shape[0]-rolling_window+1): #Loop to do regression for each time period of rolling window
        x = X[i:rolling_window+i] # The X variables for regression based on rolling window
        y = Y[i:rolling_window+i] # The Y variable for regression based on rolling window
        regressor = LinearRegression().fit(x, y) # Doing the linear regression
        temp = np.append(regressor.coef_,regressor.intercept_) # Constructing the results of the regression numpy arrray by appending the alpha to the betas
        result_array = np.vstack((result_array, np.resize(temp,(1,len(factors_to_plot)+1)))) # Appending the Results of regression to result_array

    result_array = np.delete(result_array, 0, 0) # Deleing the first initialized row of the result_array
    dates = dates[rolling_window-1:] # Determing the dates of all the days on which rolling window regression is done
    result_df = pd.DataFrame(result_array.round(decimals=2), index=dates) # Values rounded to make the plots of beta
    result_df.columns = factors1
    
    # To insert date column in the result_df dataframe
    df3 = pd.DataFrame(data=list(dates), columns=['int_date'])
    df3[['str_date']] = df3[['int_date']].applymap(str).applymap(lambda s: "{}-{}-{}".format(s[0:4], s[4:6], s[6:] ))
    rolling_dates=list(df3['str_date'])
    # df[['str_date']] = df[['int_date']].applymap(str).applymap(lambda s: "{}/{}/{}".format(s[6:], s[4:6], s[0:4]))
    dates = np.array(rolling_dates, dtype=np.datetime64)
    result_df.insert(loc=0, column='Date', value=dates)
    rolling_ndays = len(dates)
    
    mypalette=Spectral11[:4]+Spectral11[8:]
    numlines=len(factors_to_plot)

    f = figure(title = f'Rolling Beta of Factors: {rolling_window} days window', plot_height=550, plot_width=1500, 
               toolbar_location='above',x_axis_type="datetime", x_axis_location="above", background_fill_color="#efefef", 
               x_range=(dates[(rolling_ndays)//3], dates[((rolling_ndays)*2)//3])) #tooltips=tooltips,tools="xpan", 
    select1 = figure(title="Drag the middle and edges of the selection box to change the range above",
                    plot_height=140, plot_width=1500, y_range=f.y_range,
                    x_axis_type="datetime", y_axis_type=None,
                    tools="", toolbar_location=None, background_fill_color="#efefef")
    date = list(result_df['Date'])

    f.title.text_color = mypalette[-1]
    f.title.text_alpha = 0.6
    f.title.text_font = "antiqua"
    f.title.text_font_size = "32px"
    f.title.align = "center"
    f.yaxis.axis_label = 'Rolling Beta'


    for i in range(numlines):
        f.line(x=date, y=list(result_df[factors_to_plot[i]]), legend_label=factors_to_plot[i], color=mypalette[i],line_width=3,name=factors_to_plot[i])

    hover_tool = HoverTool(
        tooltips=[
            ( 'Date',   '$x{%F}'),
            ( 'Beta',   '@y' ), # use @{ } for field names with spaces
            ( 'Factor', '$name')
        ],
        formatters={
            '$x'        : 'datetime', # use 'datetime' formatter for '@date' field
        },
        names = factors_to_plot,
        mode='vline' # display a tooltip whenever the cursor is vertically in line with a glyph
    )
    f.tools.append(hover_tool)    
    f.legend.click_policy="hide"
    f.legend.background_fill_alpha = 0
    f.legend.border_line_color = None
    f.legend.margin = 10
    f.legend.padding = 18
    f.legend.spacing = 10
    f.toolbar.logo = None

    f.yaxis.axis_label_text_font_size= "18px"
    f.axis.major_label_text_font_size = '16px'
    f.legend.label_text_font_size = '16px'

    range_tool = RangeTool(x_range=f.x_range)
    range_tool.overlay.fill_color = "navy"
    range_tool.overlay.fill_alpha = 0.2

    for i in range(numlines):
        select1.line(x=date, y=list(result_df[factors_to_plot[i]]), color=mypalette[i],line_width=1,name=factors_to_plot[i])

    select1.ygrid.grid_line_color = None
    select1.add_tools(range_tool)
    select1.toolbar.active_multi = range_tool
    return column(f,select1)
示例#23
0
    if x_widget.value=='MOJE DATA - SMLOUVY': osa_x="PARTNER"
    if x_widget.value=='PLNĚNÍ EE (%)': osa_x="Plnění EE"
    if x_widget.value=='PLNĚNÍ EE (ABS)': osa_x="Plnění EE_abs"
    if x_widget.value=='SCORE_MEAN': osa_x="score_mean"
    if x_widget.value=='SCORE_MIN': osa_x="score_min"

    if y_widget.value=='MOJE DATA - SMLOUVY': osa_y="PARTNER"
    if y_widget.value=='PLNĚNÍ EE (%)': osa_y="Plnění EE"
    if y_widget.value=='PLNĚNÍ EE (ABS)': osa_y="Plnění EE_abs"
    if y_widget.value=='SCORE_MEAN': osa_y="score_mean"
    if y_widget.value=='SCORE_MIN': osa_y="score_min"
     
    scatter_cds.data = dict(x=corr_zc_tymy_filtr[osa_x],y=corr_zc_tymy_filtr[osa_y],color=corr_zc_tymy_filtr["color"],ZC=corr_zc_tymy_filtr["ZC"],Agent=corr_zc_tymy_filtr["ID agenta/cesty"])            



hover = HoverTool(tooltips=[('ZC', '@ZC'),('Agent','@Agent')])
p=figure(title="Vztah plnění a spokojenosti, jednotliví agenti", tools=["box_zoom","lasso_select","reset",hover])
p.circle("x", "y",color="color", size=10,source=scatter_cds)

region_widget.on_change('value', printer_double)
mesice_widget.on_change('value', printer_double)

x_widget.on_change('value', printer_double)
y_widget.on_change('value', printer_double)

controls = column(region_widget, mesice_widget,x_widget,y_widget)

curdoc().add_root(row(p, controls))
curdoc().title = "ZC"
示例#24
0
mytext2_ypos = int(daily_counts[len(daily_counts) - 1]) - 10
mytext2 = Label(x=1,
                y=mytext2_ypos,
                text='Day 0 (first detected case): 07 March 2020')

plot2 = figure(x_range=x,
               plot_width=700,
               plot_height=350,
               title="Number of daily positive cases")

plot2.vbar(x='x', top='daily_counts', width=0.9, source=source)
plot2.title.text_font_size = "20pt"
plot2.xaxis.axis_label = "Day"
plot2.xaxis.axis_label_text_font = "times"
plot2.xaxis.axis_label_text_font_style = "normal"
plot2.xaxis.major_label_text_font_size = "10pt"
plot2.xaxis.major_label_orientation = np.pi / 2
plot2.xaxis.axis_label_text_font_size = "15pt"
plot2.xaxis.ticker = SingleIntervalTicker(interval=2)
plot2.yaxis.axis_label = "No. of Cases"
plot2.yaxis.axis_label_text_font = "times"
plot2.yaxis.axis_label_text_font_style = "normal"
plot2.yaxis.major_label_text_font_size = "10pt"
plot2.yaxis.axis_label_text_font_size = "15pt"

plot2.add_tools(
    HoverTool(tooltips=[("DATE", "@x"), ("No. of cases", "@daily_counts")]))
plot2.add_layout(mytext2)
save(plot2)
示例#25
0
from capture import df
from bokeh.plotting import figure, show, output_file
from bokeh.models import HoverTool, ColumnDataSource

df["Start_string"] = df["Start"].dt.strftime("%Y-%m-%d %H:%M:%S")
df["End_string"] = df["End"].dt.strftime("%Y-%m-%d %H:%M:%S")
cds = ColumnDataSource(df)

p = figure(x_axis_type="datetime",
           height=100,
           width=500,
           sizing_mode="stretch_both",
           title="Motion graph")
p.yaxis.minor_tick_line_color = None
p.yaxis[0].ticker.desired_num_ticks = 1

hover = HoverTool(tooltips=[("Start", "@Start_string"), ("End",
                                                         "@End_string")])
p.add_tools(hover)

q = p.quad(left="Start",
           right="End",
           bottom=0,
           top=1,
           color="green",
           source=cds)

output_file("Graphic.html")
show(p)
示例#26
0
def plot_a_two_parameter_landscape(multi_landscape: multiparameter_landscape,
                                   index: int,
                                   TOOLTIPS=None,
                                   high=None,
                                   x_axis_label=None,
                                   y_axis_label=None):
    if (index > multi_landscape.maximum_landscape_depth) or (index < 0):
        raise TypeError('Index out of range')

    if TOOLTIPS is None:
        TOOLTIPS = [("x", "$x"), ("y", "$y"), ("value", "@image")]

    if high is None:
        high = np.max(multi_landscape.landscape_matrix[index, :, :])

    color_mapper = LinearColorMapper(palette=inferno(256), low=0, high=high)

    source = ColumnDataSource(
        data=dict(image=[
            landscape_matrix_to_img(multi_landscape.landscape_matrix[
                index, :, :])
        ],
                  x=[multi_landscape.bounds.lower_left[0]],
                  y=[multi_landscape.bounds.lower_left[1]],
                  dw=[
                      multi_landscape.bounds.upper_right[0] -
                      multi_landscape.bounds.lower_left[0]
                  ],
                  dh=[
                      multi_landscape.bounds.upper_right[1] -
                      multi_landscape.bounds.lower_left[1]
                  ]))

    plot = figure(x_range=Range1d(multi_landscape.bounds.lower_left[0],
                                  multi_landscape.bounds.upper_right[0],
                                  bounds='auto'),
                  y_range=Range1d(multi_landscape.bounds.lower_left[1],
                                  multi_landscape.bounds.upper_right[1],
                                  bounds='auto'),
                  title="Multiparameter Landscape k=" + str(index + 1),
                  width=250,
                  height=250,
                  sizing_mode='scale_both',
                  match_aspect=True,
                  toolbar_location=None)

    if x_axis_label is not None:
        plot.xaxis.axis_label = x_axis_label
    if y_axis_label is not None:
        plot.yaxis.axis_label = y_axis_label

    img = plot.image(source=source.data,
                     image='image',
                     x='x',
                     y='y',
                     dw='dw',
                     dh='dh',
                     color_mapper=color_mapper)

    img_hover = HoverTool(renderers=[img], tooltips=TOOLTIPS)
    plot.add_tools(img_hover)

    return plot
示例#27
0
# Active, New, Recovered, Dead, Rt, % Immunine
source_active = ColumnDataSource(data=dict(x=x, y=y1))
source_new = ColumnDataSource(data=dict(x=x, y=y2))
source_rec = ColumnDataSource(data=dict(x=x, y=y3))
source_dead = ColumnDataSource(data=dict(x=x, y=y4))
source_rt = ColumnDataSource(data=dict(x=x, y=y5))
source_im = ColumnDataSource(data=dict(x=x, y=y6))
source_na = ColumnDataSource(data=dict(x=x, y=y7))
source_ra = ColumnDataSource(data=dict(x=x, y=y8))
source_da = ColumnDataSource(data=dict(x=x, y=y9))
source_ic = ColumnDataSource(data=dict(x=x, y=y10))
source_pr = ColumnDataSource(data=dict(x=x, y=y11))

# plot 1

hover = HoverTool(tooltips=[(PLOT_X_LABEL, "@x{0}"), (PLOT_Y_LABEL, "@y{0}")],
                  mode="vline")
hover.point_policy = 'snap_to_data'
hover.line_policy = 'nearest'

plot = figure(
    plot_height=PLOT_HEIGHT,
    plot_width=PLOT_WIDTH,
    title=PLOT_TITLE,
    tools=PLOT_TOOLS,
    x_range=[0, DAYS],
)
plot.xaxis.axis_label = PLOT_X_LABEL
plot.yaxis.axis_label = PLOT_Y_LABEL
plot.add_tools(hover)
plot.toolbar.active_inspect = None
示例#28
0
    title="New Jersey Unemployment, 2009", tools=TOOLS,
    x_axis_location=None, y_axis_location=None
)

#returns the model specified in the argument i.e Hovertool
hover = p.select_one(HoverTool)
#Whether the tooltip position should snap to the “center” (or other anchor) position of the associated glyph, or always follow the 
#current mouse cursor position.
hover.point_policy = "follow_mouse"
#hover.
tooltips = [
    ("NUMBER_OF_PERSONS_INJURED", "@Number_Of_Persons_Injured"),
    ("(Lon, Lat)", "($x, $y)"),
]




circle= Circle(x="lon",
               y="lat",
               fill_color={'field': "Number_Of_Persons_Injured",'transform': color_mapper},
               fill_alpha=0.7)
circle_renderer = plot.add_glyph(source,circle)

plot.add_tools(HoverTool(tooltips=tooltips, renderers=[circle_renderer]))



show(plot)

示例#29
0
def roi_cost(width, height, title_text, title_align):
    df = pd.read_sql(
        """SELECT YEAR([P].[DATA]) AS [ROK], [P].[SEC_COST] AS [KOSZT], [PREMIUM].[PREMIUM] FROM
                        [PORTFEL_IN_TIME_VW] AS [P],
                        (SELECT YEAR([DATA]) AS [ROK], MAX([DATA]) AS [MAXDATA] FROM [PORTFEL_IN_TIME_VW] GROUP BY YEAR([DATA])) AS [DATES],
                        (SELECT [ROK], SUM([VAL]) AS [PREMIUM] FROM [PREMIUM_VW] GROUP BY [ROK]) AS [PREMIUM]
                        WHERE [P].[NAZWA] = 'Razem'
                        AND [P].[DATA] = [DATES].[MAXDATA]
                        AND YEAR([P].[DATA]) = [PREMIUM].[ROK]
                        OPTION (MAXRECURSION 0)""", conn)
    #wyliczenie ROI
    df['ROI'] = df['PREMIUM'] / df['KOSZT']
    #dane
    source = ColumnDataSource(data=df)
    p = figure(x_range=(min(df['ROK']) - 0.35, max(df['ROK']) + 0.35),
               plot_width=width,
               plot_height=height,
               toolbar_location=None)

    #oś dodatkowa dla ROI
    p.extra_y_ranges = {'roi': Range1d(start=0, end=max(df['ROI']) * 1.5)}
    p.add_layout(LinearAxis(y_range_name='roi'), 'right')

    #budowa słupków
    p.vbar(name='KOSZT',
           x='ROK',
           top='KOSZT',
           width=0.5,
           color=colors[0],
           source=source)
    #linia z ROI
    p.line(name='ROI',
           x='ROK',
           y='ROI',
           line_width=5,
           color=colors[1],
           source=source,
           y_range_name='roi')

    hover = HoverTool(tooltips=[('', '@ROK'), ('Koszt', '@KOSZT{0,0.00}'),
                                ('Przychody', '@PREMIUM{0,0.00}'),
                                ('ROI', '@ROI{0,0.00%}')],
                      mode='mouse',
                      renderers=[p.renderers[0]])
    p.add_tools(hover)
    p.yaxis[0].formatter = NumeralTickFormatter(format="0,00 a")
    p.yaxis[0].axis_label = "Koszt portfela"
    p.yaxis[1].formatter = NumeralTickFormatter(format="0.00 %")
    p.yaxis[1].axis_label = "Stopa zwrotu"
    p.xaxis.ticker.max_interval = 1
    p.xaxis.ticker.min_interval = 1
    p.axis.minor_tick_in = 0
    p.axis.minor_tick_out = 0
    p.ygrid.grid_line_width = 0
    p.xgrid.grid_line_width = 0
    p.outline_line_color = None
    p.border_fill_color = None
    #tytuł
    p.title.text = title_text
    p.title.align = title_align
    return p
示例#30
0
def monitors(doc):
    ## Streaming Update Function
    def update():
        global cfg
        global s1
        global s2
        global s3

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

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

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

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

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

    global cfg

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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