示例#1
0
    def retrieve(self, request, id=None):
        """ Gets the chart and saves as an html file when this route is hit
        """
        parsed_url = request.current_route_url()
        chart_type = urlparse(parsed_url).query.split('=')[1]

        if chart_type == 'candlestick':
            res = requests.get(f'{API_URL}/stock/{id}/chart/5y')
            data = res.json()
            df = pd.DataFrame(data)
            seqs = np.arange(df.shape[0])
            df['seqs'] = pd.Series(seqs)
            df['changePercent'] = df['changePercent'].apply(
                lambda x: str(x) + '%')
            # axis of one means go down the comumns, not the whole row. Default of 0 operates on the rows.
            df['mid'] = df.apply(lambda x: (x['open'] + x['close']) / 2,
                                 axis=1)
            df.head(1)
            df['height'] = df.apply(lambda x: x['close'] - x['open']
                                    if x['close'] != x['open'] else 0.001,
                                    axis=1)
            df.sample(2)
            inc = df.close > df.open
            dec = df.close < df.open
            w = .3
            sourceInc = bk.ColumnDataSource(df.loc[inc])
            sourceDec = bk.ColumnDataSource(df.loc[dec])
            hover = HoverTool(tooltips=[
                ('date', '@date'),
                ('low', '@low'),
                ('high', '@high'),
                ('open', '@open'),
                ('close', '@close'),
                ('percent', '@percent'),
            ])
            TOOLS = [
                hover,
                BoxZoomTool(),
                PanTool(),
                ZoomInTool(),
                ZoomOutTool(),
                ResetTool()
            ]
            p = bk.figure(plot_width=1500,
                          plot_height=800,
                          tools=TOOLS,
                          title=f'{id.upper()}',
                          toolbar_location='above')
            p.xaxis.major_label_orientation = np.pi / 4
            p.grid.grid_line_alpha = w
            descriptor = Label(x=70, y=70, text=f'{id}')
            # adds label onto the chart
            p.add_layout(descriptor)
            # set up your outer tails, and then the rectangles that go inside of the tails
            p.segment(df.seqs[inc],
                      df.high[inc],
                      df.seqs[inc],
                      df.low[inc],
                      color='green')
            p.segment(df.seqs[dec],
                      df.high[dec],
                      df.seqs[dec],
                      df.low[dec],
                      color='red')
            p.rect(x='seqs',
                   y='mid',
                   width=w,
                   height='height',
                   fill_color='green',
                   line_color='green',
                   source=sourceInc)
            p.rect(x='seqs',
                   y='mid',
                   width=w,
                   height='height',
                   fill_color='red',
                   line_color='red',
                   source=sourceDec)
            bk.save(p,
                    f'./stocks_api_project/static/candle_stick_{id}.html',
                    title=f'5yr_candlestick_{id}')
            f = codecs.open(
                f'./stocks_api_project/static/candle_stick_{id}.html', 'r')
            body = f.read()
            return Response(body=body, status=200)

        if chart_type == 'bar':
            res = requests.get(f'{API_URL}/stock/{id}/chart/5y')
            data = res.json()
            df = pd.DataFrame(data)
            df['date'] = pd.to_datetime(df['date'])
            df['MONTH'] = df['date'].dt.month
            df['DAY'] = df['date'].dt.day
            df['YEAR'] = df['date'].dt.year
            df[['low']].groupby(df.YEAR).mean()
            plot = bk.figure(plot_width=400, plot_height=400)
            plot.vbar(x=df.YEAR,
                      width=0.5,
                      bottom=0,
                      top=df.low,
                      color="firebrick")

            bk.save(plot,
                    f'./stocks_api_project/static/year_versus_low_{id}.html',
                    title=f'5yr_low_bar_{id}')
            f = codecs.open(
                f'./stocks_api_project/static/year_versus_low_{id}.html', 'r')
            body = f.read()
            return Response(body=body, status=200)

        if chart_type == 'volatility':
            res = requests.get(f'{API_URL}/stock/{id}/chart/5y')
            data = res.json()
            df = pd.DataFrame(data)
            df['date'] = pd.to_datetime(df['date'])
            df['MONTH'] = df['date'].dt.month
            df['DAY'] = df['date'].dt.day
            df['YEAR'] = df['date'].dt.year
            df[['change']].groupby(df.DAY).mean()
            plot_2 = bk.figure(plot_width=400, plot_height=400)
            plot_2.vbar(x=df.DAY,
                        width=0.5,
                        bottom=0,
                        top=df.change,
                        color="blue")

            bk.save(plot_2,
                    f'./stocks_api_project/static/volatility_{id}.html',
                    title=f'5yr_volitility_bar_{id}')
            f = codecs.open(
                f'./stocks_api_project/static/volatility_{id}.html', 'r')
            body = f.read()
            return Response(body=body, status=200)
示例#2
0
def std_distance_time_plot(nx, ny, source, x_range=None):
    groups = list(related_statistics(source, ACTIVE_TIME))
    if not groups:
        # original monochrome plot
        return multi_dot_plot(nx,
                              ny,
                              TIME, [ACTIVE_TIME_H, ACTIVE_DISTANCE_KM],
                              source, ['black', 'grey'],
                              alphas=[1, 0.5],
                              x_range=x_range,
                              rescale=True)
    times = [f'{ACTIVE_TIME} ({group})' for group in groups]
    distances = [f'{ACTIVE_DISTANCE} ({group})' for group in groups]
    time_y_range = make_range(source, ACTIVE_TIME_H)
    distance_y_range = make_range(source, ACTIVE_DISTANCE_KM)
    colours = list(evenly_spaced_hues(len(groups)))
    tools = [
        PanTool(dimensions='width'),
        ZoomInTool(dimensions='width'),
        ZoomOutTool(dimensions='width'),
        ResetTool(),
        HoverTool(tooltips=[
            tooltip(x) for x in (ACTIVE_TIME_H, ACTIVE_DISTANCE_KM,
                                 ACTIVITY_GROUP, LOCAL_TIME)
        ],
                  names=['with_hover'])
    ]
    f = figure(plot_width=nx,
               plot_height=ny,
               x_axis_type='datetime',
               tools=tools)
    f.yaxis.axis_label = ACTIVE_TIME_H
    f.y_range = time_y_range
    f.extra_y_ranges = {ACTIVE_DISTANCE: distance_y_range}
    f.add_layout(
        LinearAxis(y_range_name=ACTIVE_DISTANCE,
                   axis_label=ACTIVE_DISTANCE_KM), 'right')
    plotter = dot_plotter()
    for time, colour in zip(times, colours):
        time_h = _slash(time, H)
        source[time_h] = source[time] / 3600
        plotter(f,
                x=TIME,
                y=time_h,
                source=source,
                color=colour,
                alpha=1,
                name='with_hover')
    for distance, colour in zip(distances, colours):
        distance_km = _slash(distance, KM)
        source[distance_km] = source[distance] / 1000
        plotter(f,
                x=TIME,
                y=distance_km,
                source=source,
                color=colour,
                alpha=0.5,
                name='with_hover',
                y_range_name=ACTIVE_DISTANCE)
    f.xaxis.axis_label = TIME
    f.toolbar.logo = None
    if ny < 300: f.toolbar_location = None
    if x_range: f.x_range = x_range
    return f
示例#3
0
    def list(self, id=None):
        res = requests.get(f'{API_URL}stock/{SYMBOL}/company')
        data = res.json()
        company_name = data['companyName']

        data = res.json()
        df = pd.DataFrame(data)
        df.shape
        seqs = np.arange(df.shape[0])
        df['seqs'] = pd.Series(seqs)

        df['changePercent'] = df['changePercent'].apply(
            lambda x: float(x) + '%')
        df.sample(20)

        df['mid'] = df.apply(lambda x: (x['open'] + x['close']) / 2, axis=1)

        df['height'] = df.apply(lambda x: x['close'] - x['open']
                                if x['close'] != x['open'] else 0.000,
                                axis=1)

        inc = df.close > df.open
        dec = df.close < df.open
        w = .3

        sourceInc = bk.ColumnDataSource(df.loc[inc])
        sourceDec = bk.ColumnDataSource(df.loc[dec])

        hover = HoverTool(tooltips=[
            ('date', '@date'),
            ('low', '@low'),
            ('high', '@high'),
            ('open', '@open'),
            ('close', '@close'),
            ('percent', '@changePercent'),
        ])

        TOOLS = [
            hover,
            BoxZoomTool(),
            PanTool(),
            ZoomInTool(),
            ZoomOutTool(),
            ResetTool()
        ]

        p = bk.figure(plot_width=1000,
                      plot_height=800,
                      tools=TOOLS,
                      title=f'{company_name}',
                      toolbar_location='above')

        p.xaxis.major_label_orientation = np.pi / 4
        p.grid.grid_line_alpha = w

        descriptor = Label(x=70, y=70, text='')
        p.add_layout(descriptor)

        p.segment(df.seqs[inc],
                  df.high[inc],
                  df.seqs[inc],
                  df.low[inc],
                  color='green')

        p.segment(df.seqs[dec],
                  df.high[dec],
                  df.seqs[dec],
                  df.low[dec],
                  color='red')

        p.rect(x='seqs',
               y='mid',
               width=w,
               height='height',
               fill_color='green',
               line_color='green',
               source=sourceInc)

        p.rect(x='seqs',
               y='mid',
               width=w,
               height='height',
               fill_color='red',
               line_color='red',
               source=sourceDec)

        bk.save(p,
                f'../static/{company_name}_candle_stick.html',
                title=f'{company_name}_5yr_candlestick')

        return Response(json='Graph Visuals', status=200)
示例#4
0
def large_plot(n):
    from bokeh.models import (Plot, LinearAxis, Grid, GlyphRenderer,
                              ColumnDataSource, DataRange1d, PanTool,
                              ZoomInTool, ZoomOutTool, WheelZoomTool,
                              BoxZoomTool, BoxSelectTool, SaveTool, ResetTool)
    from bokeh.models.layouts import Column
    from bokeh.models.glyphs import Line

    col = Column()
    objects = set([col])

    for i in range(n):
        source = ColumnDataSource(data=dict(x=[0, i + 1], y=[0, i + 1]))
        xdr = DataRange1d()
        ydr = DataRange1d()
        plot = Plot(x_range=xdr, y_range=ydr)
        xaxis = LinearAxis()
        plot.add_layout(xaxis, "below")
        yaxis = LinearAxis()
        plot.add_layout(yaxis, "left")
        xgrid = Grid(dimension=0)
        plot.add_layout(xgrid, "center")
        ygrid = Grid(dimension=1)
        plot.add_layout(ygrid, "center")
        tickers = [
            xaxis.ticker, xaxis.formatter, yaxis.ticker, yaxis.formatter
        ]
        glyph = Line(x='x', y='y')
        renderer = GlyphRenderer(data_source=source, glyph=glyph)
        plot.renderers.append(renderer)
        pan = PanTool()
        zoom_in = ZoomInTool()
        zoom_out = ZoomOutTool()
        wheel_zoom = WheelZoomTool()
        box_zoom = BoxZoomTool()
        box_select = BoxSelectTool()
        save = SaveTool()
        reset = ResetTool()
        tools = [
            pan, zoom_in, zoom_out, wheel_zoom, box_zoom, box_select, save,
            reset
        ]
        plot.add_tools(*tools)
        col.children.append(plot)
        objects |= set([
            xdr,
            ydr,
            xaxis,
            yaxis,
            xgrid,
            ygrid,
            renderer,
            renderer.view,
            glyph,
            source,
            source.selected,
            source.selection_policy,
            plot,
            plot.x_scale,
            plot.y_scale,
            plot.toolbar,
            plot.title,
            box_zoom.overlay,
            box_select.overlay,
        ] + tickers + tools)

    return col, objects
示例#5
0
    def visualize(self):

        # Suppress various bokeh warnings
        warnings.filterwarnings("ignore")

        flag_list = []
        acuteImpacts = AcuteImpacts(targetDir=self.sourceDir,
                                    facilityIds=self.facilityIds,
                                    parameters=[self.basepath])

        flag_df = acuteImpacts.createDataframe()

        for index, row in flag_df.iterrows():
            if row[hq_rel] >= 1.5:
                flag_list.append((row[fac_id], row.pollutant, "REL"))
            if row[hq_aegl1] >= 1.5:
                flag_list.append((row[fac_id], row.pollutant, "AEGL-1 1-hr"))
            if row[hq_erpg1] >= 1.5:
                flag_list.append((row[fac_id], row.pollutant, "ERPG-1"))
            if row[hq_aegl2] >= 1.5:
                flag_list.append((row[fac_id], row.pollutant, "AEGL-2 1-hr"))
            if row[hq_erpg2] >= 1.5:
                flag_list.append((row[fac_id], row.pollutant, "ERPG-2"))

        flag_list.sort()

        # If the flag file has no cases of interest, don't do anything.
        # Otherwise, create a directory for the created acute files.
        if len(flag_list) == 0:
            Logger.logMessage(
                "Acute impacts visualization - " +
                "No acute impact was greater than or equal to 1.5. No HTML files were generated."
            )
            return
        else:
            if os.path.isdir(self.sourceDir + '/Acute Maps') == 0:
                os.mkdir(self.sourceDir + '/Acute Maps')

        # Find the HEM dose-response library and create df of it
        # Under the HEM4 dir names, "Reference" would be "Resources"
        RefFile = 'resources/Dose_Response_Library.xlsx'
        RefDF = pd.read_excel(RefFile)
        RefDF['Pollutant'] = RefDF['Pollutant'].str.lower()
        RefDF.set_index('Pollutant', inplace=True)
        RefDict = {'REL': 'REL\n(mg/m3)',\
                   'AEGL-1 1-hr':'AEGL-1  (1-hr)\n(mg/m3)',\
                   'ERPG-1':'ERPG-1\n(mg/m3)',\
                   'AEGL-2 1-hr':'AEGL-2  (1-hr)\n(mg/m3)',\
                   'ERPG-2':'ERPG-2\n(mg/m3)',\
                   'AEGL-1 8-hr':'AEGL-1  (8-hr)\n(mg/m3)',\
                   'AEGL-2 8-hr':'AEGL-2  (8-hr)\n(mg/m3)'}

        tablist = []
        for acuteset in (flag_list):

            Fac = acuteset[0]
            HAP = acuteset[1]
            refType = acuteset[2]

            path = self.sourceDir + '/' + Fac + '/'

            HAP = HAP.lower()

            # Find the all polar file for a given facility, create df of it
            allpolar = AllPolarReceptors(targetDir=path,
                                         facilityId=Fac,
                                         acuteyn='Y')
            allpolar_df = allpolar.createDataframe()
            allpolar_df[pollutant] = allpolar_df[pollutant].str.lower()

            # Find the reference value
            ref_typ_col = RefDict[refType]
            refVal = RefDF.loc[HAP, ref_typ_col]

            # Aggregate the all polar file to get HQ for each receptor
            allpolar_df.set_index('pollutant', inplace=True)
            HAP_df = allpolar_df.loc[HAP, :]
            f = {distance: 'first', angle: 'first', aconc: 'sum'}
            df = HAP_df.groupby([lat, lon], as_index=False).agg(f)
            df['HQ'] = df[aconc] / refVal / 1000
            ac_File = '%s%s%s%s%s' % (self.sourceDir, '/Acute Maps/',
                                      Fac + '_', HAP + '_', refType + '.csv')
            df.to_csv(path_or_buf=ac_File, mode='w+')

            #Convert df to geo df
            df['Coordinates'] = list(zip(df.lon, df.lat))
            df['Coordinates'] = df['Coordinates'].apply(Point)
            gdf = gp.GeoDataFrame(df,
                                  geometry='Coordinates',
                                  crs={'init': 'epsg:4326'})
            gdf = gdf.to_crs(epsg=3857)

            ESRI_tile = WMTSTileSource(
                url=
                'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{Z}/{Y}/{X}.jpg'
            )

            gdf['x'] = gdf.centroid.map(lambda p: p.x)
            gdf['y'] = gdf.centroid.map(lambda p: p.y)
            avg_x = gdf['x'].mean()
            avg_y = gdf['y'].mean()
            gdf = gdf.drop('Coordinates', axis=1)
            gdf['HQ'] = gdf['HQ'].map(lambda x: '%.1g' % x)
            gdf['lat'] = gdf['lat'].map(lambda x: '%.6f' % x)
            gdf['lon'] = gdf['lon'].map(lambda x: '%.6f' % x)
            gdf['angle'] = gdf['angle'].map(lambda x: '%.1f' % x)

            source = ColumnDataSource(gdf)

            tooltips = [("Latitude", "@lat"), ("Longitude", "@lon"),
                        ("Acute HQ", "@HQ"), ("Distance (m)", "@distance"),
                        ("Angle (deg)", "@angle")]

            title = '%s %s Acute HQ (%s)' % (Fac, HAP.title(), refType)
            tools = [ZoomInTool(), ZoomOutTool(), PanTool(),\
                       WheelZoomTool(), ResetTool(), HoverTool(tooltips=tooltips)]

            p = figure(plot_width=800, plot_height=600, tools = tools,\
                       x_range=(avg_x-3000, avg_x+3000), y_range=(avg_y-3000, avg_y+3000),\
                       title=title)

            p.toolbar.active_scroll = p.select_one(WheelZoomTool)
            p.add_tile(ESRI_tile)
            p.add_tile(STAMEN_TONER_LABELS)

            p.circle('x', 'y', color='yellow', size=7, source=source)
            p.xaxis.visible = False
            p.yaxis.visible = False
            p.xgrid.visible = False
            p.ygrid.visible = False
            p.background_fill_color = None
            p.border_fill_color = None

            #            labels = LabelSet(x='x', y='y', text='HQ', source = source,\
            #                              level='glyph', x_offset=0, y_offset=0, text_font_size='8pt',\
            #                              text_color='black', background_fill_color='yellow',\
            #                              text_font_style='bold', text_align='center', text_baseline='middle')

            labels = LabelSet(x='x', y='y', text='HQ', source = source,\
                              x_offset=0, y_offset=0, text_font_size='8pt',\
                              text_color='black', background_fill_color='yellow',\
                              text_font_style='bold', text_align='center', text_baseline='middle')
            p.add_layout(labels)
            curdoc().add_root(p)

            mapName = '%s%s%s%s%s' % (self.sourceDir, '/Acute Maps/',
                                      Fac + '_', HAP + '_', refType + '.html')
            save(p, filename=mapName)
            tab = Panel(child=p, title=HAP.title() + " (" + refType + ")")
            tablist.append(tab)

        tabs = Tabs(tabs=tablist)
        curdoc().add_root(tabs)

        mapName2 = '%s%s%s' % (self.sourceDir, '/Acute Maps/',
                               "All Acute Maps.html")
        save(tabs, filename=mapName2, title="All Acute HQ Maps")

        Logger.logMessage(
            "Acute impacts visualization - HTML files successfully created.")
示例#6
0
def make_tools(y):
    tools = [PanTool(dimensions='width'),
             ZoomInTool(dimensions='width'), ZoomOutTool(dimensions='width'),
             ResetTool(),
             HoverTool(tooltips=[tooltip(x) for x in (y, DISTANCE_KM, LOCAL_TIME)])]
    return tools
               "html/{}-service-graphs.html".format(team).lower()))

    plot_list = []

    hover = HoverTool(
        tooltips=[('Service', '@service_name'), (
            'Check Number',
            '@check_num'), ('Total Points',
                            '@total_points'), ('Check Time',
                                               '@str_datetimes')])

    TOOLS = [
        PanTool(),
        WheelZoomTool(),
        BoxZoomTool(),
        ZoomInTool(),
        ZoomOutTool(),
        UndoTool(), hover,
        ResetTool(),
        SaveTool()
    ]

    all_services_plot = figure(
        title="{} - {}".format(team, service),
        x_axis_label='Time',
        y_axis_label='{} Service Points'.format(service),
        x_axis_type="datetime",
        x_range=Range1d(x_start, x_end),
        width=GRAPH_WIDTH,
        height=GRAPH_HEIGHT,
        tools=TOOLS)
示例#8
0
hover_bar = HoverTool(tooltips=[('Rating','@x1'),
                                ('Number of Business','@y1')
							])

hover_pie = HoverTool(tooltips=[('Percentage','@ratio')
							])

select_day = Select(
                options=['Sunday','Monday', 'Tuesday', 'Wednesday', 'Thursday','Friday','Saturday'],
                value='Monday',
                title='Day of the Week'
)

chosen_tools =[hover,ResetTool(),BoxSelectTool(),
               SaveTool(),PanTool(),
               UndoTool(),RedoTool(),ZoomInTool(),
               ZoomOutTool()
               ]

#data
data = pd.read_csv(r'~/Desktop/yelp/yelp_business.csv',index_col='business_id')
hour = pd.read_csv(r'~/Desktop/yelp/yelp_business_hours.csv',index_col='business_id')
#data = pd.read_csv(r'E:\project\CIS4170\yelp\yelp_business.csv',index_col='business_id')
#hour = pd.read_csv(r'E:\project\CIS4170\yelp\yelp_business_hours.csv',index_col='business_id')
whole = pd.merge(data,hour, left_index=True, right_index=True)

#data = pd.read_csv(r'E:\Software\WinPython\notebooks\yelp\yelp_business.csv',index_col='business_id')
state_data = whole[whole.state=='NV']
categoricaldata = state_data.categories.str.contains('')
open_data = state_data.loc[state_data[select_day.value.lower()] != 'None']
new_data = open_data.where(categoricaldata).dropna(thresh = 19).sort_values(by=['stars'],ascending=False)
示例#9
0
def map_create(prot_pop_geo, prot_pop):

    geosource = GeoJSONDataSource(
        geojson=simplejson.dumps(simplejson.loads(prot_pop_geo.to_json())))

    # ----- Raw count map -----

    # initialize figure
    palette = cividis(256)

    hover_a = HoverTool(tooltips=[('Country', '@name'), ('Protests',
                                                         '@protest')])
    color_mapper_a = LogColorMapper(palette=palette,
                                    low=1,
                                    high=prot_pop['protest'].max() + 5,
                                    nan_color='#ffffff')
    color_bar_a = ColorBar(
        color_mapper=color_mapper_a,
        ticker=LogTicker(),
        orientation='horizontal',
        border_line_color=None,
        location=(0, 0),
        label_standoff=8,
        major_label_text_font='Raleway',
        major_label_text_font_size='12pt',
        title='Number of registered Fridays for Future protests',
        title_text_font_style='normal',
        title_text_font='Raleway',
        title_text_font_size='15pt')

    p_a = figure(
        title=
        'The Fridays for Future movement grew to global scale within only 10 months',
        tools=[hover_a,
               ZoomInTool(),
               ZoomOutTool(),
               ResetTool(),
               PanTool()],
        plot_height=600,
        plot_width=980)

    # add patch renderer
    p_a.patches('xs',
                'ys',
                source=geosource,
                fill_color={
                    'field': 'protest',
                    'transform': color_mapper_a
                },
                line_color='black',
                line_width=0.25,
                fill_alpha=1)

    # prettify
    p_a.xgrid.grid_line_color = None
    p_a.ygrid.grid_line_color = None
    p_a.outline_line_color = None
    p_a.axis.visible = False
    p_a.add_layout(color_bar_a, 'below')
    p_a.toolbar.logo = None
    p_a.title.text_font = "Raleway"
    p_a.title.text_font_style = "normal"
    p_a.title.align = 'center'
    p_a.title.text_color = 'black'
    p_a.title.text_font_size = '20pt'

    tab_a = Panel(child=p_a, title="Absolute number")

    # ----- Population adjusted count map -----

    # initialize figure
    hover_b = HoverTool(tooltips=[(
        'Country',
        '@name'), ('Protests per 10 million',
                   '@prot_ptm'), ('Protests',
                                  '@protest'), ('Population', '@population')])
    color_mapper_b = LogColorMapper(
        palette=palette,
        low=prot_pop['prot_ptm'].min(),
        high=float(prot_pop.loc[prot_pop['code'] == 'GRL']['prot_ptm']) + 10,
        nan_color='#ffffff')
    color_bar_b = ColorBar(
        color_mapper=color_mapper_b,
        ticker=LogTicker(),
        orientation='horizontal',
        border_line_color=None,
        location=(0, 0),
        label_standoff=8,
        major_label_text_font='Raleway',
        major_label_text_font_size='12pt',
        title='Number of registered Fridays for Future protests per 10 million',
        title_text_font_style='normal',
        title_text_font='Raleway',
        title_text_font_size='15pt')

    p_b = figure(
        title=
        'The Fridays for Future movement grew to global scale within only 10 months',
        tools=[hover_b,
               ZoomInTool(),
               ZoomOutTool(),
               ResetTool(),
               PanTool()],
        plot_height=600,
        plot_width=980)

    # add patch renderer
    p_b.patches('xs',
                'ys',
                source=geosource,
                fill_color={
                    'field': 'prot_ptm',
                    'transform': color_mapper_b
                },
                line_color='black',
                line_width=0.25,
                fill_alpha=1)

    # prettify
    p_b.xgrid.grid_line_color = None
    p_b.ygrid.grid_line_color = None
    p_b.outline_line_color = None
    p_b.axis.visible = False
    p_b.add_layout(color_bar_b, 'below')
    p_b.toolbar.logo = None
    p_b.title.text_font = "Raleway"
    p_b.title.text_font_style = "normal"
    p_b.title.align = 'center'
    p_b.title.text_color = 'black'
    p_b.title.text_font_size = '20pt'

    tab_b = Panel(child=p_b, title="Population normalized")

    tabs = Tabs(tabs=[tab_a, tab_b])

    return tabs
示例#10
0
           plot_width=1200,
           title='S&P 500',
           x_axis_label='Date',
           y_axis_label='Close (in USD)')
p.line(sp500_df['Date'], sp500_df['Close'], color='blue', legend='')

# Hover tool with vline mode
hover = HoverTool(
    tooltips=[('Close', '$@{Close}{%0.2f}'), ('Date', '@date{%F}')],
    formatters={
        'date': 'datetime',  # use 'datetime' formatter for 'date' field
        'Close': 'printf',  # use 'printf' formatter for 'adj close' field
        # use default 'numeral' formatter for other fields
    },
    mode='vline')

p.add_tools(hover)
p.add_tools(LassoSelectTool())
p.add_tools(PolySelectTool())
p.add_tools(TapTool())
p.add_tools(UndoTool())
p.add_tools(RedoTool())
p.add_tools(ResetTool())
p.add_tools(ZoomInTool())
p.add_tools(ZoomOutTool())
p.add_tools(CrosshairTool())

html = file_html(p, CDN, "my plot")

with open("./test_bokeh.html", "w") as html_file:
    html_file.write(html)
示例#11
0
def __make_daybyday_interactive_timeline(
    df: pd.DataFrame,
    *,
    geo_df: geopandas.GeoDataFrame,
    value_col: str,
    transform_df_func: Callable[[pd.DataFrame], pd.DataFrame] = None,
    stage: Union[DiseaseStage, Literal[Select.ALL]] = Select.ALL,
    count: Union[Counting, Literal[Select.ALL]] = Select.ALL,
    out_file_basename: str,
    subplot_title_prefix: str,
    plot_aspect_ratio: float = None,
    cmap=None,
    n_cbar_buckets: int = None,
    n_buckets_btwn_major_ticks: int = None,
    n_minor_ticks_btwn_major_ticks: int = None,
    per_capita_denominator: int = None,
    x_range: Tuple[float, float],
    y_range: Tuple[float, float],
    min_visible_y_range: float,
    should_make_video: bool,
) -> InfoForAutoload:
    """Create the bokeh interactive timeline plot(s)

    This function takes the given DataFrame, which must contain COVID data for locations
    on different dates, and a GeoDataFrame, which contains the long/lat coords for those
    locations, and creates an interactive choropleth of the COVID data over time.

    :param df: The COVID data DataFrame
    :type df: pd.DataFrame
    :param geo_df: The geometry GeoDataFrame for the locations in `df`
    :type geo_df: geopandas.GeoDataFrame
    :param value_col: The column of `df` containing the values to plot in the
    choropleth; should be something like "Case_Counts" or "Case_Diff_From_Prev_Day"
    :type value_col: str
    :param stage: The DiseaseStage to plot, defaults to Select.ALL. If ALL, then all
    stages are plotted and are stacked vertically.
    :type stage: Union[DiseaseStage, Literal[Select.ALL]], optional
    :param count: The Counting to plot, defaults to Select.ALL. If ALL, then all
    count types are plotted and are stacked horizontally.
    :type count: Union[Counting, Literal[Select.ALL]], optional
    :param out_file_basename: The basename of the file to save the interactive plots to
    (there are two components, the JS script and the HTML <div>)
    :type out_file_basename: str
    :param subplot_title_prefix: What the first part of the subplot title should be;
    probably a function of `value_col` (if value_col is "Case_Counts" then this param
    might be "Cases" or "# of Cases")
    :type subplot_title_prefix: str
    :param x_range: The range of the x-axis as (min, max)
    :type x_range: Tuple[float, float]
    :param y_range: The range of the y-axis as (min, max)
    :type y_range: Tuple[float, float]
    :param min_visible_y_range: The minimum height (in axis units) of the y-axis; it
    will not be possible to zoom in farther than this on the choropleth.
    :type min_visible_y_range: float
    :param should_make_video: Optionally run through the timeline day by day, capture
    a screenshot for each day, and then stitch the screenshots into a video. The video
    shows the same info as the interactive plots, but not interactively. This easily
    takes 20x as long as just making the graphs themselves, so use with caution.
    :type should_make_video: bool
    :param transform_df_func: This function expects data in a certain format, and does
    a bunch of preprocessing (expected to be common) before plotting. This gives you a
    chance to do any customization on the postprocessed df before it's plotted. Defaults
    to None, in which case no additional transformation is performed.
    :type transform_df_func: Callable[[pd.DataFrame], pd.DataFrame], optional
    :param plot_aspect_ratio: The aspect ratio of the plot as width/height; if set, the
    aspect ratio will be fixed to this. Defaults to None, in which case the aspect ratio
    is determined from the x_range and y_range arguments
    :type plot_aspect_ratio: float, optional
    :param cmap: The colormap to use as either a matplotlib-compatible colormap or a
    list of hex strings (e.g., ["#ae8f1c", ...]). Defaults to None in which case a
    reasonable default is used.
    :type cmap: Matplotlib-compatible colormap or List[str], optional
    :param n_cbar_buckets: How many colorbar buckets to use. Has little effect if the
    colormap is continuous, but always works in conjunction with
    n_buckets_btwn_major_ticks to determine the number of major ticks. Defaults to 6.
    :type n_cbar_buckets: int, optional
    :param n_buckets_btwn_major_ticks: How many buckets are to lie between colorbar
    major ticks, determining how many major ticks are drawn. Defaults to 1.
    :type n_buckets_btwn_major_ticks: int, optional
    :param n_minor_ticks_btwn_major_ticks: How many minor ticks to draw between colorbar
    major ticks. Defaults to 8 (which means each pair of major ticks has 10 ticks
    total).
    :type n_minor_ticks_btwn_major_ticks: int, optional
    :param per_capita_denominator: When describing per-capita numbers, what to use as
    the denominator (e.g., cases per 100,000 people). If None, it is automatically
    computed per plot to be appropriately scaled for the data.
    :type per_capita_denominator: int, optional
    :raises ValueError: [description]
    :return: The two pieces of info required to make a Bokeh autoloading HTML+JS plot:
    the HTML div to be inserted somewhere in the HTML body, and the JS file that will
    load the plot into that div.
    :rtype: InfoForAutoload
    """

    Counting.verify(count, allow_select=True)
    DiseaseStage.verify(stage, allow_select=True)

    # The date as a string, so that bokeh can use it as a column name
    STRING_DATE_COL = "String_Date_"
    # A column whose sole purpose is to be a (the same) date associated with each
    # location
    FAKE_DATE_COL = "Fake_Date_"
    # The column we'll actually use for the colors; it's computed from value_col
    COLOR_COL = "Color_"

    # Under no circumstances may you change this date format
    # It's not just a pretty date representation; it actually has to match up with the
    # date strings computed in JS
    DATE_FMT = r"%Y-%m-%d"

    ID_COLS = [
        REGION_NAME_COL,
        Columns.DATE,
        Columns.STAGE,
        Columns.COUNT_TYPE,
    ]

    if cmap is None:
        cmap = cmocean.cm.matter

    if n_cbar_buckets is None:
        n_cbar_buckets = 6

    if n_buckets_btwn_major_ticks is None:
        n_buckets_btwn_major_ticks = 1

    if n_minor_ticks_btwn_major_ticks is None:
        n_minor_ticks_btwn_major_ticks = 8

    n_cbar_major_ticks = n_cbar_buckets // n_buckets_btwn_major_ticks + 1

    try:
        color_list = [
            # Convert matplotlib colormap to bokeh (list of hex strings)
            # https://stackoverflow.com/a/49934218
            RGB(*rgb).to_hex()
            for i, rgb in enumerate((255 * cmap(range(256))).astype("int"))
        ]
    except TypeError:
        color_list = cmap

    color_list: List[BokehColor]

    if stage is Select.ALL:
        stage_list = list(DiseaseStage)
    else:
        stage_list = [stage]

    if count is Select.ALL:
        count_list = list(Counting)
    else:
        count_list = [count]

    stage_list: List[DiseaseStage]
    count_list: List[Counting]

    stage_count_list: List[Tuple[DiseaseStage, Counting]] = list(
        itertools.product(stage_list, count_list))

    df = df.copy()

    # Unadjust dates (see SaveFormats._adjust_dates)
    normalized_dates = df[Columns.DATE].dt.normalize()
    is_at_midnight = df[Columns.DATE] == normalized_dates
    df.loc[is_at_midnight, Columns.DATE] -= pd.Timedelta(days=1)
    df.loc[~is_at_midnight, Columns.DATE] = normalized_dates[~is_at_midnight]

    min_date, max_date = df[Columns.DATE].agg(["min", "max"])
    dates: List[pd.Timestamp] = pd.date_range(start=min_date,
                                              end=max_date,
                                              freq="D")
    max_date_str = max_date.strftime(DATE_FMT)

    # Get day-by-day case diffs per location, date, stage, count-type

    # Make sure data exists for every date for every state so that the entire country is
    # plotted each day; fill missing data with 0 (missing really *is* as good as 0)
    # enums will be replaced by their name (kind of important)
    id_cols_product: pd.MultiIndex = pd.MultiIndex.from_product(
        [
            df[REGION_NAME_COL].unique(),
            dates,
            [s.name for s in DiseaseStage],
            [c.name for c in Counting],
        ],
        names=ID_COLS,
    )

    df = (id_cols_product.to_frame(index=False).merge(
        df,
        how="left",
        on=ID_COLS,
    ).sort_values(ID_COLS))

    df[STRING_DATE_COL] = df[Columns.DATE].dt.strftime(DATE_FMT)
    df[Columns.CASE_COUNT] = df[Columns.CASE_COUNT].fillna(0)

    if transform_df_func is not None:
        df = transform_df_func(df)

    df = geo_df.merge(df, how="inner", on=REGION_NAME_COL)[[
        REGION_NAME_COL,
        Columns.DATE,
        STRING_DATE_COL,
        Columns.STAGE,
        Columns.COUNT_TYPE,
        value_col,
    ]]

    dates: List[pd.Timestamp] = [
        pd.Timestamp(d) for d in df[Columns.DATE].unique()
    ]

    values_mins_maxs = (df[df[value_col] > 0].groupby(
        [Columns.STAGE, Columns.COUNT_TYPE])[value_col].agg(["min", "max"]))

    vmins: pd.Series = values_mins_maxs["min"]
    vmaxs: pd.Series = values_mins_maxs["max"]

    pow10s_series: pd.Series = vmaxs.map(
        lambda x: int(10**(-np.floor(np.log10(x)))))

    # _pow_10s_series_dict = {}
    # for stage in DiseaseStage:
    #     _pow_10s_series_dict.update(
    #         {
    #             (stage.name, Counting.TOTAL_CASES.name): 100000,
    #             (stage.name, Counting.PER_CAPITA.name): 10000,
    #         }
    #     )

    # pow10s_series = pd.Series(_pow_10s_series_dict)

    vmins: dict = vmins.to_dict()
    vmaxs: dict = vmaxs.to_dict()

    for stage in DiseaseStage:
        _value_key = (stage.name, Counting.PER_CAPITA.name)
        if per_capita_denominator is None:
            _max_pow10 = pow10s_series.loc[(slice(None),
                                            Counting.PER_CAPITA.name)].max()
        else:
            _max_pow10 = per_capita_denominator

        vmins[_value_key] *= _max_pow10
        vmaxs[_value_key] *= _max_pow10
        pow10s_series[_value_key] = _max_pow10

    percap_pow10s: pd.Series = df.apply(
        lambda row: pow10s_series[
            (row[Columns.STAGE], row[Columns.COUNT_TYPE])],
        axis=1,
    )

    _per_cap_rows = df[Columns.COUNT_TYPE] == Counting.PER_CAPITA.name
    df.loc[_per_cap_rows, value_col] *= percap_pow10s.loc[_per_cap_rows]

    # Ideally we wouldn't have to pivot, and we could do a JIT join of state longs/lats
    # after filtering the data. Unfortunately this is not possible, and a long data
    # format leads to duplication of the very large long/lat lists; pivoting is how we
    # avoid that. (This seems to be one downside of bokeh when compared to plotly)
    df = (df.pivot_table(
        index=[REGION_NAME_COL, Columns.STAGE, Columns.COUNT_TYPE],
        columns=STRING_DATE_COL,
        values=value_col,
        aggfunc="first",
    ).reset_index().merge(
        geo_df[[REGION_NAME_COL, LONG_COL, LAT_COL]],
        how="inner",
        on=REGION_NAME_COL,
    ))

    # All three oclumns are just initial values; they'll change with the date slider
    df[value_col] = df[max_date_str]
    df[FAKE_DATE_COL] = max_date_str
    df[COLOR_COL] = np.where(df[value_col] > 0, df[value_col], "NaN")

    # Technically takes a df but we don't need the index
    bokeh_data_source = ColumnDataSource(
        {k: v.tolist()
         for k, v in df.to_dict(orient="series").items()})

    filters = [[
        GroupFilter(column_name=Columns.STAGE, group=stage.name),
        GroupFilter(column_name=Columns.COUNT_TYPE, group=count.name),
    ] for stage, count in stage_count_list]

    figures = []

    for subplot_index, (stage, count) in enumerate(stage_count_list):
        # fig = bplotting.figure()
        # ax: plt.Axes = fig.add_subplot(
        #     len(stage_list), len(count_list), subplot_index
        # )

        # # Add timestamp to top right axis
        # if subplot_index == 2:
        #     ax.text(
        #         1.25,  # Coords are arbitrary magic numbers
        #         1.23,
        #         f"Last updated {NOW_STR}",
        #         horizontalalignment="right",
        #         fontsize="small",
        #         transform=ax.transAxes,
        #     )

        view = CDSView(source=bokeh_data_source,
                       filters=filters[subplot_index])

        vmin = vmins[(stage.name, count.name)]
        vmax = vmaxs[(stage.name, count.name)]

        # Compute and set axes titles
        if stage is DiseaseStage.CONFIRMED:
            fig_stage_name = "Cases"
        elif stage is DiseaseStage.DEATH:
            fig_stage_name = "Deaths"
        else:
            raise ValueError

        fig_title_components: List[str] = []
        if subplot_title_prefix is not None:
            fig_title_components.append(subplot_title_prefix)

        fig_title_components.append(fig_stage_name)

        if count is Counting.PER_CAPITA:
            _per_cap_denom = pow10s_series[(stage.name, count.name)]
            fig_title_components.append(f"Per {_per_cap_denom:,d} people")
            formatter = PrintfTickFormatter(format=r"%2.3f")
            label_standoff = 12
            tooltip_fmt = "{0.000}"
        else:
            formatter = NumeralTickFormatter(format="0.0a")
            label_standoff = 10
            tooltip_fmt = "{0}"

        color_mapper = LogColorMapper(
            color_list,
            low=vmin,
            high=vmax,
            nan_color="#f2f2f2",
        )

        fig_title = " ".join(fig_title_components)

        if plot_aspect_ratio is None:
            if x_range is None or y_range is None:
                raise ValueError("Must provide both `x_range` and `y_range`" +
                                 " when `plot_aspect_ratio` is None")
            plot_aspect_ratio = (x_range[1] - x_range[0]) / (y_range[1] -
                                                             y_range[0])

        # Create figure object
        p = bplotting.figure(
            title=fig_title,
            title_location="above",
            tools=[
                HoverTool(
                    tooltips=[
                        ("Date", f"@{{{FAKE_DATE_COL}}}"),
                        ("State", f"@{{{REGION_NAME_COL}}}"),
                        ("Count", f"@{{{value_col}}}{tooltip_fmt}"),
                    ],
                    toggleable=False,
                ),
                PanTool(),
                BoxZoomTool(match_aspect=True),
                ZoomInTool(),
                ZoomOutTool(),
                ResetTool(),
            ],
            active_drag=None,
            aspect_ratio=plot_aspect_ratio,
            output_backend="webgl",
            lod_factor=4,
            lod_interval=400,
            lod_threshold=1000,
            lod_timeout=300,
        )

        p.xgrid.grid_line_color = None
        p.ygrid.grid_line_color = None
        # Finally, add the actual choropleth data we care about
        p.patches(
            LONG_COL,
            LAT_COL,
            source=bokeh_data_source,
            view=view,
            fill_color={
                "field": COLOR_COL,
                "transform": color_mapper
            },
            line_color="black",
            line_width=0.25,
            fill_alpha=1,
        )

        # Add evenly spaced ticks and their labels to the colorbar
        # First major, then minor
        # Adapted from https://stackoverflow.com/a/50314773
        bucket_size = (vmax / vmin)**(1 / n_cbar_buckets)
        tick_dist = bucket_size**n_buckets_btwn_major_ticks

        # Simple log scale math
        major_tick_locs = (
            vmin * (tick_dist**np.arange(0, n_cbar_major_ticks))
            # * (bucket_size ** 0.5) # Use this if centering ticks on buckets
        )
        # Get minor locs by linearly interpolating between major ticks
        minor_tick_locs = []
        for major_tick_index, this_major_tick in enumerate(
                major_tick_locs[:-1]):
            next_major_tick = major_tick_locs[major_tick_index + 1]

            # Get minor ticks as numbers in range [this_major_tick, next_major_tick]
            # and exclude the major ticks themselves (once we've used them to
            # compute the minor tick locs)
            minor_tick_locs.extend(
                np.linspace(
                    this_major_tick,
                    next_major_tick,
                    n_minor_ticks_btwn_major_ticks + 2,
                )[1:-1])

        color_bar = ColorBar(
            color_mapper=color_mapper,
            ticker=FixedTicker(ticks=major_tick_locs,
                               minor_ticks=minor_tick_locs),
            formatter=formatter,
            label_standoff=label_standoff,
            major_tick_out=0,
            major_tick_in=13,
            major_tick_line_color="white",
            major_tick_line_width=1,
            minor_tick_out=0,
            minor_tick_in=5,
            minor_tick_line_color="white",
            minor_tick_line_width=1,
            location=(0, 0),
            border_line_color=None,
            bar_line_color=None,
            orientation="vertical",
        )

        p.add_layout(color_bar, "right")
        p.hover.point_policy = "follow_mouse"

        # Bokeh axes (and most other things) are splattable
        p.axis.visible = False

        figures.append(p)

    # Make all figs pan and zoom together by setting their axes equal to each other
    # Also fix the plots' aspect ratios
    figs_iter = iter(np.ravel(figures))
    anchor_fig = next(figs_iter)

    if x_range is not None and y_range is not None:
        data_aspect_ratio = (x_range[1] - x_range[0]) / (y_range[1] -
                                                         y_range[0])
    else:
        data_aspect_ratio = plot_aspect_ratio

    if x_range is not None:
        anchor_fig.x_range = Range1d(
            *x_range,
            bounds="auto",
            min_interval=min_visible_y_range * data_aspect_ratio,
        )

    if y_range is not None:
        anchor_fig.y_range = Range1d(*y_range,
                                     bounds="auto",
                                     min_interval=min_visible_y_range)

    for fig in figs_iter:
        fig.x_range = anchor_fig.x_range
        fig.y_range = anchor_fig.y_range

    # 2x2 grid (for now)
    gp = gridplot(
        figures,
        ncols=len(count_list),
        sizing_mode="scale_both",
        toolbar_location="above",
    )
    plot_layout = [gp]

    # Ok, pause
    # Now we're going into a whole other thing: we're doing all the JS logic behind a
    # date slider that changes which date is shown on the graphs. The structure of the
    # data is one column per date, one row per location, and a few extra columns to
    # store the data the graph will use. When we adjust the date of the slider, we copy
    # the relevant column of the df into the columns the graphs are looking at.
    # That's the easy part; the hard part is handling the "play button" functionality,
    # whereby the user can click one button and the date slider will periodically
    # advance itself. That requires a fair bit of logic to schedule and cancel the
    # timers and make it all feel right.

    # Create unique ID for the JS playback info object for this plot (since it'll be on
    # the webpage with other plots, and their playback info isn't shared)
    _THIS_PLOT_ID = uuid.uuid4().hex

    __TIMER = "'timer'"
    __IS_ACTIVE = "'isActive'"
    __SELECTED_INDEX = "'selectedIndex'"
    __BASE_INTERVAL_MS = "'BASE_INTERVAL'"  # Time (in MS) btwn frames when speed==1
    __TIMER_START_DATE = "'startDate'"
    __TIMER_ELAPSED_TIME_MS = "'elapsedTimeMS'"
    __TIMER_ELAPSED_TIME_PROPORTION = "'elapsedTimeProportion'"
    __SPEEDS_KEY = "'SPEEDS'"
    __PLAYBACK_INFO = f"window._playbackInfo_{_THIS_PLOT_ID}"

    _PBI_TIMER = f"{__PLAYBACK_INFO}[{__TIMER}]"
    _PBI_IS_ACTIVE = f"{__PLAYBACK_INFO}[{__IS_ACTIVE}]"
    _PBI_SELECTED_INDEX = f"{__PLAYBACK_INFO}[{__SELECTED_INDEX}]"
    _PBI_TIMER_START_DATE = f"{__PLAYBACK_INFO}[{__TIMER_START_DATE}]"
    _PBI_TIMER_ELAPSED_TIME_MS = f"{__PLAYBACK_INFO}[{__TIMER_ELAPSED_TIME_MS}]"
    _PBI_TIMER_ELAPSED_TIME_PROPORTION = (
        f"{__PLAYBACK_INFO}[{__TIMER_ELAPSED_TIME_PROPORTION}]")
    _PBI_BASE_INTERVAL = f"{__PLAYBACK_INFO}[{__BASE_INTERVAL_MS}]"
    _PBI_SPEEDS = f"{__PLAYBACK_INFO}[{__SPEEDS_KEY}]"
    _PBI_CURR_INTERVAL_MS = (
        f"{_PBI_BASE_INTERVAL} / {_PBI_SPEEDS}[{_PBI_SELECTED_INDEX}]")

    _SPEED_OPTIONS = [0.25, 0.5, 1.0, 2.0]
    _DEFAULT_SPEED = 1.0
    _DEFAULT_SELECTED_INDEX = _SPEED_OPTIONS.index(_DEFAULT_SPEED)

    _SETUP_WINDOW_PLAYBACK_INFO = f"""
        if (typeof({__PLAYBACK_INFO}) === 'undefined') {{
            {__PLAYBACK_INFO} = {{
                {__TIMER}: null,
                {__IS_ACTIVE}: false,
                {__SELECTED_INDEX}: {_DEFAULT_SELECTED_INDEX},
                {__TIMER_START_DATE}: null,
                {__TIMER_ELAPSED_TIME_MS}: 0,
                {__TIMER_ELAPSED_TIME_PROPORTION}: 0,
                {__BASE_INTERVAL_MS}: 1000,
                {__SPEEDS_KEY}: {_SPEED_OPTIONS}
            }};
        }}

    """

    _DEFFUN_INCR_DATE = f"""
        // See this link for why this works (it's an undocumented feature?)
        // https://discourse.bokeh.org/t/5254
        // Tl;dr we need this to automatically update the hover as the play button plays
        // Without this, the hover tooltip only updates when we jiggle the mouse
        // slightly

        let prev_val = null;
        source.inspect.connect(v => prev_val = v);

        function updateDate() {{
            {_PBI_TIMER_START_DATE} = new Date();
            {_PBI_TIMER_ELAPSED_TIME_MS} = 0
            if (dateSlider.value < maxDate) {{
                dateSlider.value += 86400000;
            }}

            if (dateSlider.value >= maxDate) {{
                console.log(dateSlider.value, maxDate)
                console.log('reached end')
                clearInterval({_PBI_TIMER});
                {_PBI_IS_ACTIVE} = false;
                playPauseButton.active = false;
                playPauseButton.change.emit();
                playPauseButton.label = 'Restart';
            }}

            dateSlider.change.emit();

            // This is pt. 2 of the prev_val/inspect stuff above
            if (prev_val !== null) {{
                source.inspect.emit(prev_val);
            }}
        }}
    """

    _DO_START_TIMER = f"""
        function startLoopTimer() {{
            updateDate();
            if ({_PBI_IS_ACTIVE}) {{
                {_PBI_TIMER} = setInterval(updateDate, {_PBI_CURR_INTERVAL_MS})
            }}

        }}

        {_PBI_TIMER_START_DATE} = new Date();

        // Should never be <0 or >1 but I am being very defensive here
        const proportionRemaining = 1 - (
            {_PBI_TIMER_ELAPSED_TIME_PROPORTION} <= 0
            ? 0
            : {_PBI_TIMER_ELAPSED_TIME_PROPORTION} >= 1
            ? 1
            : {_PBI_TIMER_ELAPSED_TIME_PROPORTION}
        );
        const remainingTimeMS = (
            {_PBI_CURR_INTERVAL_MS} * proportionRemaining
        );
        const initialInterval = (
            {_PBI_TIMER_ELAPSED_TIME_MS} === 0
            ? 0
            : remainingTimeMS
        );

        {_PBI_TIMER} = setTimeout(
            startLoopTimer,
            initialInterval
        );
    """

    _DO_STOP_TIMER = f"""
        const now = new Date();
        {_PBI_TIMER_ELAPSED_TIME_MS} += (
            now.getTime() - {_PBI_TIMER_START_DATE}.getTime()
        );
        {_PBI_TIMER_ELAPSED_TIME_PROPORTION} = (
            {_PBI_TIMER_ELAPSED_TIME_MS} / {_PBI_CURR_INTERVAL_MS}
        );
        clearInterval({_PBI_TIMER});
    """

    update_on_date_change_callback = CustomJS(
        args={"source": bokeh_data_source},
        code=f"""

        {_SETUP_WINDOW_PLAYBACK_INFO}

        const sliderValue = cb_obj.value;
        const sliderDate = new Date(sliderValue)
        // Ugh, actually requiring the date to be YYYY-MM-DD (matching DATE_FMT)
        const dateStr = sliderDate.toISOString().split('T')[0]

        const data = source.data;

        {_PBI_TIMER_ELAPSED_TIME_MS} = 0

        if (typeof(data[dateStr]) !== 'undefined') {{
            data['{value_col}'] = data[dateStr]

            const valueCol = data['{value_col}'];
            const colorCol = data['{COLOR_COL}'];
            const fakeDateCol = data['{FAKE_DATE_COL}']

            for (var i = 0; i < data['{value_col}'].length; i++) {{
                const value = valueCol[i]
                if (value == 0) {{
                    colorCol[i] = 'NaN';
                }} else {{
                    colorCol[i] = value;
                }}

                fakeDateCol[i] = dateStr;
            }}

            source.change.emit();

        }}

        """,
    )

    # Taking day-over-day diffs means the min slider day is one more than the min data
    # date (might be off by 1 if not using day over diffs but in practice not an issue)
    min_slider_date = min_date + pd.Timedelta(days=1)
    date_slider = DateSlider(
        start=min_slider_date,
        end=max_date,
        value=max_date,
        step=1,
        sizing_mode="stretch_width",
        width_policy="fit",
    )
    date_slider.js_on_change("value", update_on_date_change_callback)

    play_pause_button = Toggle(
        label="Start playing",
        button_type="success",
        active=False,
        sizing_mode="stretch_width",
    )

    animate_playback_callback = CustomJS(
        args={
            "source": bokeh_data_source,
            "dateSlider": date_slider,
            "playPauseButton": play_pause_button,
            "maxDate": max_date,
            "minDate": min_slider_date,
        },
        code=f"""

        {_SETUP_WINDOW_PLAYBACK_INFO}
        {_DEFFUN_INCR_DATE}

        if (dateSlider.value >= maxDate) {{
            if (playPauseButton.active) {{
                dateSlider.value = minDate;
                dateSlider.change.emit();

                // Hack to get timer to wait after date slider wraps; any positive
                // number works but the smaller the better
                {_PBI_TIMER_ELAPSED_TIME_MS} = 1;
            }}
        }}

        const active = cb_obj.active;
        {_PBI_IS_ACTIVE} = active;

        if (active) {{
            playPauseButton.label = 'Playing – Click/tap to pause'
            {_DO_START_TIMER}
        }} else {{
            playPauseButton.label = 'Paused – Click/tap to play'
            {_DO_STOP_TIMER}
        }}

        """,
    )

    play_pause_button.js_on_click(animate_playback_callback)

    change_playback_speed_callback = CustomJS(
        args={
            "source": bokeh_data_source,
            "dateSlider": date_slider,
            "playPauseButton": play_pause_button,
            "maxDate": max_date,
        },
        code=f"""

        {_SETUP_WINDOW_PLAYBACK_INFO}
        {_DEFFUN_INCR_DATE}

        // Must stop timer before handling changing the speed, as stopping the timer
        // saves values based on the current (unchaged) speed selection
        if ({_PBI_TIMER} !== null) {{
            {_DO_STOP_TIMER}
        }}

        const selectedIndex = cb_obj.active;
        {_PBI_SELECTED_INDEX} = selectedIndex;

        if ({_PBI_IS_ACTIVE}) {{
            {_DO_START_TIMER}
        }} else {{
            {_PBI_TIMER_ELAPSED_TIME_MS} = 0
        }}

        console.log({__PLAYBACK_INFO})

    """,
    )

    playback_speed_radio = RadioButtonGroup(
        labels=[f"{speed:.2g}x speed" for speed in _SPEED_OPTIONS],
        active=_DEFAULT_SELECTED_INDEX,
        sizing_mode="stretch_width",
    )
    playback_speed_radio.js_on_click(change_playback_speed_callback)

    plot_layout.append(
        layout_column(
            [
                date_slider,
                layout_row(
                    [play_pause_button, playback_speed_radio],
                    height_policy="min",
                ),
            ],
            width_policy="fit",
            height_policy="min",
        ))
    plot_layout = layout_column(plot_layout, sizing_mode="scale_both")

    # grid = gridplot(figures, ncols=len(count_list), sizing_mode="stretch_both")

    # Create the autoloading bokeh plot info (HTML + JS)
    js_path = str(Path(out_file_basename + "_autoload").with_suffix(".js"))
    tag_html_path = str(
        Path(out_file_basename + "_div_tag").with_suffix(".html"))

    js_code, tag_code = autoload_static(plot_layout, CDN, js_path)
    tag_uuid = re.search(r'id="([^"]+)"', tag_code).group(1)
    tag_code = re.sub(r'src="([^"]+)"', f'src="\\1?uuid={tag_uuid}"', tag_code)

    with open(Paths.DOCS / js_path,
              "w") as f_js, open(Paths.DOCS / tag_html_path, "w") as f_html:
        f_js.write(js_code)
        f_html.write(tag_code)

    # Create the video by creating stills of the graphs for each date and then stitching
    # the images into a video
    if should_make_video:
        save_dir: Path = PNG_SAVE_ROOT_DIR / out_file_basename
        save_dir.mkdir(parents=True, exist_ok=True)

        STILL_WIDTH = 1500
        STILL_HEIGHT = int(np.ceil(STILL_WIDTH / plot_aspect_ratio) *
                           1.05)  # Unclear why *1.05 is necessary
        gp.height = STILL_HEIGHT
        gp.width = STILL_WIDTH
        gp.sizing_mode = "fixed"
        orig_title = anchor_fig.title.text

        for date in dates:
            date_str = date.strftime(DATE_FMT)
            anchor_fig.title = Title(text=f"{orig_title} {date_str}")

            for p in figures:
                p.title = Title(text=p.title.text, text_font_size="20px")

            # Just a reimplementation of the JS code in the date slider's callback
            data = bokeh_data_source.data
            data[value_col] = data[date_str]

            for i, value in enumerate(data[value_col]):
                if value == 0:
                    data[COLOR_COL][i] = "NaN"
                else:
                    data[COLOR_COL][i] = value

                data[FAKE_DATE_COL][i] = date_str

            save_path: Path = (save_dir / date_str).with_suffix(".png")
            export_png(gp, filename=save_path)
            resize_to_even_dims(save_path, pad_bottom=0.08)

            if date == max(dates):
                poster_path: Path = (
                    PNG_SAVE_ROOT_DIR /
                    (out_file_basename + "_poster")).with_suffix(".png")
                poster_path.write_bytes(save_path.read_bytes())

        make_video(save_dir, out_file_basename, 0.9)

    print(f"Did interactive {out_file_basename}")

    return (js_code, tag_code)
示例#12
0
    def plot_pca(self, parameter, a, b):
        result = self.result
        source1 = column_source(result, "FDA")
        source2 = column_source(result, "PPI")
        source3 = column_source(result, "MACRO")
        source4 = column_source(result, "NP")
        source5 = column_source(result, "FDA PEP")
        source6 = column_source(result, "linear")
        source7 = column_source(result, "cyclic")
        hover = HoverTool(tooltips=[
            ("PCA 1", "$x"),
            ("PCA 2", "$y"),
            ("NAME", "@N"),
        ])
        p = figure(
            title="PCA based on " + parameter[0],
            x_axis_label="PC 1" + "(" + str(a) + "%)",
            y_axis_label="PC 2" + "(" + str(b) + "%)",
            x_range=(-4, 8),
            y_range=(-4, 8),
            tools=[hover],
            plot_width=1000,
            plot_height=800,
        )
        p.add_tools(LassoSelectTool(), ZoomInTool(), ZoomOutTool(), SaveTool(),
                    PanTool())
        FDA_plot = p.circle(x="x",
                            y="y",
                            source=source1,
                            color="darkslateblue",
                            size=5)
        PPI_plot = p.circle(x="x",
                            y="y",
                            source=source2,
                            color="yellowgreen",
                            size=5)
        MACRO_plot = p.circle(x="x",
                              y="y",
                              source=source3,
                              color="lightsteelblue",
                              size=5)
        NP_plot = p.circle(x="x", y="y", source=source4, color="olive", size=5)
        PEP_FDA_plot = p.circle(x="x",
                                y="y",
                                source=source5,
                                color="lightcoral",
                                size=5)
        LIN_plot = p.circle(x="x", y="y", source=source6, color="teal", size=5)
        CYC_plot = p.circle(x="x",
                            y="y",
                            source=source7,
                            color="mediumvioletred",
                            size=5)
        legend = Legend(
            items=[
                ("FDA", [FDA_plot]),
                ("PPI", [PPI_plot]),
                ("MACRO", [MACRO_plot]),
                ("NP", [NP_plot]),
                ("PEP FDA", [PEP_FDA_plot]),
                ("LIN", [LIN_plot]),
                ("CYC", [CYC_plot]),
            ],
            location="center",
            orientation="vertical",
            click_policy="hide",
        )
        p.add_layout(legend, place="right")
        p.xaxis.axis_label_text_font_size = "20pt"
        p.yaxis.axis_label_text_font_size = "20pt"
        p.xaxis.axis_label_text_color = "black"
        p.yaxis.axis_label_text_color = "black"
        p.xaxis.major_label_text_font_size = "18pt"
        p.yaxis.major_label_text_font_size = "18pt"
        p.title.text_font_size = "22pt"

        return p
示例#13
0
def main():
    """
    An example sequence of commands to make a measurement with the P1125 REST API.

    The internal Calibration loads will be used to plot essentially DC currents of various magnitudes.
    Since internal loads are used, the Probe is not connected.
    """

    # check if the P1125 is reachable
    success, result = p1125.ping()
    logger.info("ping: {}".format(result))
    if not success: return False

    success, result = p1125.status()
    logger.info("status: {}".format(result))
    if not success: return False

    success, result = p1125.probe(connect=False)
    logger.info("probe: {}".format(result))
    if not success: return False

    success, result = p1125.calibrate()
    logger.info("calibrate: {}".format(result))
    if not success: return False

    success, result = p1125.set_timebase(SPAN)
    logger.info("set_timebase: {}".format(result))
    if not success: return False

    success, result = p1125.set_trigger(src=P1125API.TRIG_SRC_NONE,
                                        pos=P1125API.TRIG_POS_LEFT,
                                        slope=P1125API.TRIG_SLOPE_RISE,
                                        level=1)
    logger.info("set_trigger: {}".format(result))
    if not success: return False

    for vout in VOUT:

        success, result = p1125.set_vout(vout)
        logger.info("set_vout: {}".format(result))
        if not success: return False

        for load, resistance in LOADS_TO_PLOT:
            expected_i_ua = float(vout) / resistance * 1000.0
            if expected_i_ua < CURRENT_MIN_UA or expected_i_ua > CURRENT_MAX_UA:
                logger.info(
                    "SKIP (Current out of range): {} mV, {:0.3f} Ohms, expected {:.1f} uA"
                    .format(vout, resistance, expected_i_ua))
                continue

            logger.info("{} mV, {}, expected {} uA".format(
                vout, resistance, expected_i_ua))

            success, result = p1125.set_cal_load(loads=load)
            logger.info("set_cal_load: {}".format(result))
            if not success: break
            sleep(0.1)  # allow load time to settle

            success, result = p1125.acquisition_start(
                mode=P1125API.ACQUIRE_MODE_SINGLE)
            logger.info("acquisition_start: {}".format(result))
            if not success: break

            success, result = p1125.acquisition_complete()
            logger.info("acquisition_complete: {}".format(result))
            if not success: break

            p1125.set_cal_load(loads=[P1125API.DEMO_CAL_LOAD_NONE])
            p1125.acquisition_stop()

            _, result = p1125.acquisition_get_data()

            samples = len(result["i"])
            data["vout"].append(vout)
            data["min"].append(min(result["i"]))
            data["max"].append(max(result["i"]))
            data["avg"].append(sum(result["i"]) / samples)
            data["exp"].append(expected_i_ua)
            data["err"].append(
                (abs(data["avg"][-1] - data["exp"][-1]) * 100.0) /
                data["exp"][-1])
            data["res"].append(resistance)

            # find the peak error from the acquistion
            peak_error = max(abs(data["exp"][-1] - data["min"][-1]),
                             abs(data["exp"][-1] - data["max"][-1]))
            data["errp"].append(peak_error * 100.0 / data["exp"][-1])

            sigma = np.std(result["i"])
            data["sigma"].append(sigma)
            sigma_as_percent = sigma * 100.0 / data["exp"][-1]
            data["sigma_percent"].append(sigma_as_percent)
            logger.info(
                """VOUT {} mV, Expected {:9.2f} uA, min/avg/max: {:9.2f} {:9.2f} {:9.2f} uA, sigma {:8.3f} ({:3.1}%), {} samples"""
                .format(data["vout"][-1], data["exp"][-1], data["min"][-1],
                        data["avg"][-1], data["max"][-1], sigma,
                        sigma_as_percent, samples))
            # large error...
            #if data["errp"][-1] > PLOT_CIRCLE_ERR: logger.error(result["i"])

    plot.cross(x="vout", y="avg", size=10, color="blue", source=source)
    plot.dot(x="vout", y="exp", size=20, color="olive", source=source)
    plot.dash(x="vout", y="min", size=10, color="red", source=source)
    plot.dash(x="vout", y="max", size=10, color="red", source=source)

    _tooltips_sigma = [
        ("Sigma", "@sigma_percent{0.0} %"),
    ]
    dotssigma = plot_sigma.circle_dot(x="vout",
                                      y="exp",
                                      size="sigma_percent",
                                      fill_alpha=0.2,
                                      line_width=1,
                                      color="red",
                                      source=source)
    plot_sigma.circle(x="vout",
                      y="exp",
                      size=PLOT_CIRCLE_ERR,
                      fill_alpha=0.2,
                      line_width=0,
                      color="green",
                      source=source)
    htsigma = HoverTool(tooltips=_tooltips_sigma,
                        mode='vline',
                        show_arrow=True,
                        renderers=[dotssigma])
    plot_sigma.tools = [
        htsigma,
        BoxZoomTool(),
        ZoomInTool(),
        ResetTool(),
        UndoTool(),
        PanTool()
    ]

    _tooltips_peak = [
        ("Error", "@errp{0.0} %"),
    ]
    dotsp = plot_errp.circle_dot(x="vout",
                                 y="exp",
                                 size="errp",
                                 fill_alpha=0.2,
                                 color="red",
                                 source=source)
    plot_errp.circle(x="vout",
                     y="exp",
                     size=PLOT_CIRCLE_ERR,
                     fill_alpha=0.2,
                     line_width=0,
                     color="green",
                     source=source)
    htp = HoverTool(tooltips=_tooltips_peak,
                    mode='vline',
                    show_arrow=True,
                    renderers=[dotsp])
    plot_errp.tools = [
        htp,
        BoxZoomTool(),
        ZoomInTool(),
        ResetTool(),
        UndoTool(),
        PanTool()
    ]

    doc_layout.children.append(row(plot, plot_errp, plot_sigma))
    show(doc_layout)
    return True
    def plot_pca(self, parameter, a, b):
        result = self.result
        print(a, b)
        source1 = column_source(result, "APEXBIO")
        source2 = column_source(result, "Asinex")
        source3 = column_source(result, "ChemDiv")
        source4 = column_source(result, "Enamine")
        source5 = column_source(result, "Life_Chemicals")
        source6 = column_source(result, "MedChemExpress")
        source7 = column_source(result, "OTAVA_DNMT1")
        source8 = column_source(result, "OTAVA_DNMT3b")
        source9 = column_source(result, "SelleckChem")
        source10 = column_source(result, "Targetmol")
        source11 = column_source(result, "Tocris")
        hover = HoverTool(tooltips=[
            ("PCA 1", "$x"),
            ("PCA 2", "$y"),
            ("ID", "@N"),
        ])
        p = figure(
            # title="PCA based on: " + parameter,
            x_axis_label="PC 1 " + str(a) + "%",
            y_axis_label="PC 2 " + str(b) + "%",
            x_range=(-5, 10),
            y_range=(-5, 8),
            tools=[hover],
            plot_width=1000,
            plot_height=800,
        )
        p.add_tools(LassoSelectTool(), ZoomInTool(), ZoomOutTool(), SaveTool(),
                    PanTool())
        APEXBIO_plot = p.circle(x="x",
                                y="y",
                                source=source1,
                                color="mediumvioletred",
                                size=5)
        Asinex_plot = p.circle(x="x",
                               y="y",
                               source=source2,
                               color="mediumslateblue",
                               size=5)
        ChemDiv_plot = p.circle(x="x",
                                y="y",
                                source=source3,
                                color="lightsalmon",
                                size=5)
        Enamine_plot = p.circle(x="x",
                                y="y",
                                source=source4,
                                color="gold",
                                size=5)
        Life_Chemicals_plot = p.circle(x="x",
                                       y="y",
                                       source=source5,
                                       color="violet",
                                       size=5)
        MedChemExpress_plot = p.circle(x="x",
                                       y="y",
                                       source=source6,
                                       color="mediumaquamarine",
                                       size=5)
        OTAVA_DNMT1_plot = p.circle(x="x",
                                    y="y",
                                    source=source7,
                                    color="steelblue",
                                    size=5)
        OTAVA_DNMT3b_plot = p.circle(x="x",
                                     y="y",
                                     source=source8,
                                     color="navy",
                                     size=5)
        SelleckChem_plot = p.circle(x="x",
                                    y="y",
                                    source=source9,
                                    color="darkred",
                                    size=5)
        Targetmol_plot = p.circle(x="x",
                                  y="y",
                                  source=source10,
                                  color="indigo",
                                  size=5)
        Tocris_plot = p.circle(x="x",
                               y="y",
                               source=source11,
                               color="pink",
                               size=5)

        legend = Legend(
            items=[
                ("APEXBIO", [APEXBIO_plot]),
                ("Asinex", [Asinex_plot]),
                ("ChemDiv", [ChemDiv_plot]),
                ("Enamine", [Enamine_plot]),
                ("Life_Chemicals", [Life_Chemicals_plot]),
                ("MedChemExpress", [MedChemExpress_plot]),
                ("OTAVA_DNMT1", [OTAVA_DNMT1_plot]),
                ("OTAVA_DNMT3b", [OTAVA_DNMT3b_plot]),
                ("SelleckChem", [SelleckChem_plot]),
                ("Targetmol", [Targetmol_plot]),
                ("Tocris", [Tocris_plot]),
            ],
            location="center",
            orientation="vertical",
            click_policy="hide",
        )
        p.add_layout(legend, place="right")
        p.xaxis.axis_label_text_font_size = "20pt"
        p.yaxis.axis_label_text_font_size = "20pt"
        p.xaxis.axis_label_text_color = "black"
        p.yaxis.axis_label_text_color = "black"
        p.xaxis.major_label_text_font_size = "18pt"
        p.yaxis.major_label_text_font_size = "18pt"
        p.title.text_font_size = "22pt"
        #
        show(p)
        # save
        p.output_backend = "svg"
        export_svgs(
            p,
            filename="/Users/eurijuarez/Desktop/Alexis/Plots/SVG_files/" +
            "ChemSpace_PCA" + ".svg",
        )
示例#15
0
graph_circle.node_renderer.glyph            = Circle(size=10, fill_alpha=0.8, fill_color='royalblue')
graph_circle.node_renderer.selection_glyph  = Circle(size=10, fill_alpha=0.8, fill_color='red')
graph_circle.node_renderer.hover_glyph      = Circle(size=10, fill_alpha=0.8, fill_color='yellow')

graph_circle.edge_renderer.glyph            = MultiLine(line_width=3, line_alpha=0.8, line_color='color')
graph_circle.edge_renderer.selection_glyph  = MultiLine(line_width=4, line_alpha=0.8, line_color='red')
graph_circle.edge_renderer.hover_glyph      = MultiLine(line_width=4, line_alpha=0.8, line_color='yellow')
graph_circle.edge_renderer.glyph.line_width = {'field': 'weight'}

graph_circle.selection_policy = NodesAndLinkedEdges()
graph_circle.inspection_policy = NodesAndLinkedEdges()


plot_circle.add_tools(WheelZoomTool())
plot_circle.add_tools(ZoomOutTool())
plot_circle.add_tools(ZoomInTool())
plot_circle.add_tools(ResetTool())
plot_circle.add_tools(UndoTool())
plot_circle.add_tools(RedoTool())
plot_circle.add_tools(PanTool())
plot_circle.add_tools(TapTool())
plot_circle.add_tools(SaveTool())
plot_circle.add_tools(BoxSelectTool())
plot_circle.add_tools(LassoSelectTool())
# !!! Hover the node attributes !!!
node_hover = HoverTool(tooltips=[('Name', '@index'), ('Degree', '@degree'),
                                ('Min Weight', '@minweight'), ('Max Weight', '@maxweight'), ('Sum Weight', '@sumweight')])
plot_circle.add_tools(node_hover)


plot_circle.add_layout(color_bar, 'right')
 def plot(self, source1, source2, source3, source4, source5, source6,
          source7, source8, source9):
     hover = HoverTool(tooltips=[
         ("Similarity", "($x)"),
         ("ECF", "($y)"),
     ])
     p = figure(title="TOPOLOGICAL FP/Tanimoto Similarity",
                x_axis_label="Similarity",
                y_axis_label="Cumulative Distribution Function",
                x_range=(0, 1),
                y_range=(0, 1),
                tools=[hover],
                plot_width=1000,
                plot_height=800)
     FDA_plot = p.line(x="x",
                       y="y",
                       source=source1,
                       line_width=3,
                       color="darkslateblue")
     PPI_plot = p.line(x="x",
                       y="y",
                       source=source2,
                       line_width=3,
                       color="yellowgreen")
     MACRO_plot = p.line(x="x",
                         y="y",
                         source=source3,
                         line_width=3,
                         color="lightsteelblue")
     NP_plot = p.line(x="x",
                      y="y",
                      source=source4,
                      line_width=3,
                      color="olive")
     PEP_FDA_plot = p.line(x="x",
                           y="y",
                           source=source5,
                           line_width=3,
                           color="darkslategray")
     LIN_plot = p.line(x="x",
                       y="y",
                       source=source6,
                       line_width=3,
                       color="aquamarine")
     LIN_NM_plot = p.line(x="x",
                          y="y",
                          source=source7,
                          line_width=3,
                          color="teal")
     CYC_plot = p.line(x="x",
                       y="y",
                       source=source8,
                       line_width=3,
                       color="lightpink")
     CYC_NM_plot = p.line(x="x",
                          y="y",
                          source=source9,
                          line_width=3,
                          color="mediumvioletred")
     p.add_tools(LassoSelectTool(), ZoomInTool(), ZoomOutTool(), SaveTool(),
                 PanTool())
     legend = Legend(items=[
         ("FDA", [FDA_plot]),
         ("PPI", [PPI_plot]),
         ("MACRO", [MACRO_plot]),
         ("NP", [NP_plot]),
         ("PEP FDA", [PEP_FDA_plot]),
         ("LIN", [LIN_plot]),
         ("LIN NM", [LIN_NM_plot]),
         ("CYC", [CYC_plot]),
         ("CYC NM", [CYC_NM_plot]),
     ],
                     location="center",
                     orientation="vertical",
                     click_policy="hide")
     p.add_layout(legend, place='right')
     p.xaxis.axis_label_text_font_size = "20pt"
     p.yaxis.axis_label_text_font_size = "20pt"
     p.xaxis.axis_label_text_color = "black"
     p.yaxis.axis_label_text_color = "black"
     p.xaxis.major_label_text_font_size = "18pt"
     p.yaxis.major_label_text_font_size = "18pt"
     p.title.text_font_size = "22pt"
     return p
示例#17
0
def multi_plot(nx,
               ny,
               x,
               ys,
               source,
               colors,
               alphas=None,
               x_range=None,
               y_label=None,
               rescale=False,
               plotters=None):
    if not ys or not present(source, x, *ys): return None
    tools = [
        PanTool(dimensions='width'),
        ZoomInTool(dimensions='width'),
        ZoomOutTool(dimensions='width'),
        ResetTool(),
        HoverTool(tooltips=[tooltip(x) for x in ys + [LOCAL_TIME]],
                  names=['with_hover'])
    ]
    f = figure(plot_width=nx,
               plot_height=ny,
               x_axis_type='datetime' if TIME in x else 'linear',
               tools=tools)
    if y_label:
        f.yaxis.axis_label = y_label
    elif rescale:
        f.yaxis.axis_label = ys[0]
    else:
        f.yaxis.axis_label = ', '.join(ys)
    if rescale: f.extra_y_ranges = {}
    if alphas is None: alphas = [1 for _ in ys]
    while len(plotters) < len(ys):
        plotters += plotters
    for y, color, alpha, plotter in zip(ys, colors, alphas, plotters):
        y_range = make_range(source, y)
        if rescale and y != ys[0]:
            f.extra_y_ranges[y] = y_range
            f.add_layout(LinearAxis(y_range_name=y, axis_label=y), 'right')
            plotter(f,
                    x=x,
                    y=y,
                    source=source,
                    color=color,
                    alpha=alpha,
                    y_range_name=y,
                    name='with_hover')
        else:
            f.y_range = y_range
            plotter(f,
                    x=x,
                    y=y,
                    source=source,
                    color=color,
                    alpha=alpha,
                    name='with_hover')
    f.xaxis.axis_label = x
    f.toolbar.logo = None
    if ny < 300: f.toolbar_location = None
    if x_range: f.x_range = x_range
    return f
示例#18
0
def std_distance_time_plot(nx,
                           ny,
                           source,
                           x_range=None,
                           output_backend=DEFAULT_BACKEND):
    # avoid range errors
    if len(source[N.ACTIVE_TIME_S].dropna()) < 2:
        return None
    groups = [
        group
        for statistic, group in related_statistics(source, N.ACTIVE_TIME)
    ]
    if not groups:
        # original monochrome plot
        return multi_dot_plot(nx,
                              ny,
                              N.TIME, [N.ACTIVE_TIME_H, N.ACTIVE_DISTANCE_KM],
                              source, ['black', 'grey'],
                              alphas=[1, 0.5],
                              x_range=x_range,
                              rescale=True)
    times = [f'{N.ACTIVE_TIME}:{group}' for group in groups]
    distances = [f'{N.ACTIVE_DISTANCE}:{group}' for group in groups]
    time_y_range = make_range(source[N.ACTIVE_TIME_H])
    distance_y_range = make_range(source[N.ACTIVE_DISTANCE_KM])
    colours = list(evenly_spaced_hues(len(groups)))
    tooltip_names = [
        N.ACTIVE_TIME_H, N.ACTIVE_DISTANCE_KM, N.ACTIVITY_GROUP, N.LOCAL_TIME
    ]
    tooltip_names += [
        name for name in like(N._delta(N.FITNESS_ANY), source.columns)
        if ':' not in name
    ]
    tooltip_names += [
        name for name in like(N._delta(N.FATIGUE_ANY), source.columns)
        if ':' not in name
    ]
    tools = [
        PanTool(dimensions='width'),
        ZoomInTool(dimensions='width'),
        ZoomOutTool(dimensions='width'),
        ResetTool(),
        HoverTool(tooltips=[tooltip(name) for name in tooltip_names],
                  names=['with_hover'])
    ]
    f = figure(output_backend=output_backend,
               plot_width=nx,
               plot_height=ny,
               x_axis_type='datetime',
               tools=tools)
    f.yaxis.axis_label = f'lines - {N.ACTIVE_TIME_H}'
    f.y_range = time_y_range
    f.extra_y_ranges = {N.ACTIVE_DISTANCE: distance_y_range}
    f.add_layout(
        LinearAxis(y_range_name=N.ACTIVE_DISTANCE,
                   axis_label=f'dots - {N.ACTIVE_DISTANCE_KM}'), 'right')
    plotter = comb_plotter()
    for time, colour, group in zip(times, colours, groups):
        time_h = N._slash(time, U.H)
        source[time_h] = source[time] / 3600
        source[N.ACTIVITY_GROUP] = group
        plotter(f, x=N.TIME, y=time_h, source=source, color=colour, alpha=1)
    plotter = dot_plotter()
    for distance, colour, group in zip(distances, colours, groups):
        distance_km = N._slash(distance, U.KM)
        source[distance_km] = source[distance]
        source[N.ACTIVITY_GROUP] = group
        plotter(f,
                x=N.TIME,
                y=distance_km,
                source=source,
                color=colour,
                alpha=1,
                name='with_hover',
                y_range_name=N.ACTIVE_DISTANCE)
    f.xaxis.axis_label = N.TIME
    f.toolbar.logo = None
    if ny < 300: f.toolbar_location = None
    if x_range: f.x_range = x_range
    return f
示例#19
0
def SIF_Explorer_tab():

    #################################
    # Initialize all layers
    #################################

    # Load from a save file
    if path.exists(LAYERS_FILE):
        with open(LAYERS_FILE, 'rb') as layers_file:
            us_county_layer, us_state_layer, world_grid_2_degree_layer = pickle.load(layers_file)
    # Load from scratch
    else:
        us_county_layer = US_County_Layer()
        us_state_layer = US_State_Layer()
        world_grid_2_degree_layer = US_World_Grid_2_Degree_Layer()
        
        # Save the layers to file
        with open(LAYERS_FILE, 'wb') as layers_file:
            layers = (us_county_layer, \
                        us_state_layer, world_grid_2_degree_layer)
            pickle.dump(layers, layers_file)

    # Want the custom layer to be new every time
    custom_shapes_layer = Custom_Shapes_Layer()
    world_grid_dynamic_layer = World_Grid_Dynamic_Layer()

    # Set the active layer to be the county layer
    active_layer = us_county_layer

    #################################
    # Set up layer selector
    #################################

    # Once a new layer is selected, use that layer to refresh the page
    # and all data
    def refresh_page():
        
        # Get initial map details
        xs, ys, names = active_layer.get_map_details()

        if type(active_layer) != Custom_Shapes_Layer:

            # Obtain and update date boundaries
            start_date, end_date = active_layer.get_date_range()
            date_range_slider.start = start_date
            date_range_slider.end = end_date

            # Unpack the current range
            range_start, range_end = date_range_slider.value

            # Convert to SQL format
            range_start = utc_from_timestamp(range_start)
            range_end = utc_from_timestamp(range_end)

            # Get the initial sif values
            sifs = active_layer.get_data_for_date_range(range_start, 
                                                        range_end)

            # Dictionary to hold the data
            new_source_dict = dict(
                x= xs, y= ys,
                name= np.array(names), sifs= np.array(sifs))
            
            # Update all source data values
            source.data = new_source_dict

            # Turn off custom layer
            custom_data_source.data = dict(x= np.array([]), y= np.array([]), 
                                           name = np.array([]))

        else:

            # Turn off the other layers
            source.data = dict(x= np.array([]), y= np.array([]),
                name= np.array([]), sifs= np.array([]))

            # Safeguard - that at least one custom shape is drawn
            if (xs.size != 0):

                # Dictionary to hold the selected shape data
                new_source_dict = dict(
                    x= xs, y= ys,
                    name = np.array(names))

                custom_data_source.data = new_source_dict


    # Trigger for when a new layer is selected
    def layer_selected(new):

        # We want to modify the overall active layer (not local to this func)
        nonlocal active_layer

        # Simple dictionary to switch out the active layer
        switcher = {
            0 : custom_shapes_layer,
            1 : us_state_layer,
            2 : us_county_layer,
            3 : world_grid_2_degree_layer,
            4 : world_grid_dynamic_layer,
        }

        # Swap out the active layer
        active_layer = switcher.get(new, active_layer) 
            
        # Fetch new dates, shapes, names, etc. and refresh the page
        refresh_page()

    # Define selection labels
    layer_selector = RadioButtonGroup(
        labels=["Custom", "US States", "US Counties", 
                "World", "World (Dynamic)"], active=2)

    # Set up layer selection callback
    layer_selector.on_click(layer_selected)

    #################################
    # Set up date range slider
    #################################

    # Obtain date boundaries
    start_date, end_date = active_layer.get_date_range()

    # create a callback for when the date slider is changed
    def date_range_selected(attr, old, new):

        t0 = time.time()

        # Unpack the new range
        range_start, range_end = new

        # Convert to SQL format
        range_start = utc_from_timestamp(range_start)
        range_end = utc_from_timestamp(range_end)
        
        # Get the new day's data
        sifs = active_layer.get_data_for_date_range(range_start, range_end)

        # Update the sif values
        source.data["sifs"] = np.array(sifs)

        # Set the title of the map to reflect the selected date range
        p.title.text = "SIF Average: %s to %s" % (range_start, range_end)

        print("Took " + str(time.time() - t0) + " seconds to update")

    # Create the date slider
    date_range_slider = DateRangeSlider(title="Date Range: ", 
                                        start=start_date, end=end_date, 
                                        value=(START_DATE_INIT, 
                                            END_DATE_INIT), step=1)

    # Assign the callback for when the date slider changes
    date_range_slider.callback_policy = "throttle"
    date_range_slider.callback_throttle = 200
    date_range_slider.on_change('value_throttled', date_range_selected)

    #################################
    # Set up the map and its source
    #################################

    # Get initial map details
    xs, ys, names = active_layer.get_map_details()

    # Get the initial sif values 
    sifs = active_layer.get_data_for_date_range(START_DATE_INIT, 
                                                END_DATE_INIT)

    # Dictionary to hold the data
    source=ColumnDataSource(data = dict(
        x= np.array(xs),
        y= np.array(ys),
        name= np.array(names),
        sifs= np.array(sifs))
    )

    # Which tools should be available to the user
    TOOLS = "pan,wheel_zoom,reset,hover,save,tap"

    # Obtain map provider
    tile_provider = get_provider(Vendors.CARTODBPOSITRON_RETINA)

    # tile_options = {}
    # tile_options['url'] = 'https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}'
    # tile_options['attribution'] = """
    #     Map tiles by <a href="http://stamen.com">Stamen Design</a>, under
    #     <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>.
    #     Data by <a href="http://openstreetmap.org">OpenStreetMap</a>,
    #     under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.
    #     """
    # mq_tile_source = WMTSTileSource(**tile_options)

    # Don't want the map to wrap around
    tile_provider.wrap_around = False

    # Configure the figure
    p = figure(
        title="SIF Average by County: %s" % end_date, tools=TOOLS,
        active_scroll = "wheel_zoom",
        x_axis_location=None, y_axis_location=None,
        tooltips=[
            ("Name", "@name"), 
            ("Average SIF", "@sifs")
        ],
        x_axis_type='mercator',
        y_axis_type='mercator',
        plot_height = 900,
        plot_width = 1100,
        output_backend="webgl",
        x_range=Range1d(-20000000, 20000000, bounds = 'auto'))

    # Add the map!
    p.add_tile(tile_provider)

    p.lod_threshold = None          # No downsampling
    #p.lod_interval = 150
    p.toolbar.logo = None           # No logo
    p.grid.grid_line_color = None   # No grid

    # Policy for hovering
    p.hover.point_policy = "follow_mouse"

    # Color mapper
    color_mapper = LinearColorMapper(palette=palette, 
                                     low = SIF_MIN, high = SIF_MAX)
    color_transform = {'field': 'sifs', 'transform': color_mapper}

    # Patch all the information onto the map
    patch_renderer = p.patches('x', 'y', source=source,
                      fill_color=color_transform,
                      fill_alpha=0.9, line_color="white", line_width=0.1, 
                      selection_fill_alpha = 1.0, 
                      selection_fill_color = color_transform,
                      nonselection_line_color="black",
                      nonselection_fill_alpha=0.7,
                      nonselection_fill_color= color_transform)
    p.title.text_font_size = '16pt'

    # Add a color bar
    ticker = FixedTicker(ticks=[-1,0,1,2])
    color_bar = ColorBar(color_mapper=color_mapper, ticker = ticker,
                     label_standoff=12, border_line_color=None, location=(0,0))
    p.add_layout(color_bar, 'right')

    # Add zoom in / out tools
    zoom_in = ZoomInTool(factor=ZOOM_FACTOR)
    zoom_out = ZoomOutTool(factor=ZOOM_FACTOR)

    def range_changed(param, old, new):
        if (type(active_layer) == World_Grid_Dynamic_Layer):
            x1 = p.x_range.start
            x2 = p.x_range.end
            y1 = p.y_range.start
            y2 = p.y_range.end
            new_x1, new_y1 = to_lat_lon(y1, x1)
            new_x2, new_y2 = to_lat_lon(y2, x2)
            if (active_layer.range_changed(new_x1, new_y1, new_x2, new_y2)):
                refresh_page()
            #convert_shapes_to_mercator(np.array([[x1], [x2]]), 
                                                      #np.array([[y1], [y2]]))

            #print("(%s, %s) to (%s, %s)" % (x1, y1, x2, y2))
            #40000000
            #

    # p.callback_policy = "throttle"
    # p.callback_throttle = 200
    p.x_range.on_change('end', range_changed)

    p.add_tools(zoom_in)
    p.add_tools(zoom_out)

    #################################
    # Set up custom plot data
    #################################

    # Data source for custom shapes
    custom_data_source = ColumnDataSource(data = \
                                        dict(x= np.array([]), y= np.array([]), 
                                        name=np.array([])))

    # Patch the custom data onto the map
    p.patches('x', 'y', source=custom_data_source,
                  line_color="darkslategray", line_width=1, 
                  fill_alpha=0.3, fill_color="lightgray")

    # On geometry selection
    # zoom = WheelZoomTool()
    # p.on_event()
    # p.add_tools(lasso)
    # p.on_event(SelectionGeometry, shape_drawn)

    #################################
    # Set up time series
    #################################

    def color_gen():
        yield from itertools.cycle(time_pltt[10])
    color = color_gen()

    def shape_drawn(event):

        # Check if more than one point
        # Otherwise a tap triggers this function
        if (type(event.geometry['x']) != float):

            # Notify the custom selection layer that this
            # shape was selected and obtain relevant info
            # custom_shapes_layer.patch_selected(event)

            # Change to the custom layer
            layer_selector.active = 0
            layer_selected(0)

            # Notify the layer that this patch was created. 
            active_layer.patch_created(event)

            # Clear all time series
            sif_series.renderers = []

            # Update the title and get new data from the active layer
            sif_series.title.text, time_srs_src_list, names = \
                                active_layer.patch_clicked(source, None)

            # Plot each series returned
            for i in range(len(time_srs_src_list)):
                sif_series.scatter('date', 'sif', 
                                    source=time_srs_src_list[i], 
                                    color=time_pltt[10][i])
            # Make sure the current shape is drawn
            refresh_page()

    def patch_clicked(event):
        """ When a patch is clicked, update the time series chart. """

        # Clear all time series
        sif_series.renderers = []

        # Update the title and get new data from the active layer
        sif_series.title.text, time_srs_src_list, names = \
                            active_layer.patch_clicked(source, event)

        # Plot each series returned
        for i in range(len(time_srs_src_list)):
            sif_series.scatter('date', 'sif', 
                                source=time_srs_src_list[i], 
                                color=time_pltt[10][i])

    # Which tools should be available to the user for the timer series
    TOOLS = "pan,wheel_zoom,reset,hover,save"

    # Figure that holds the time-series
    sif_series = figure(plot_width=750, plot_height=400, x_axis_type='datetime',
                        tools=TOOLS, 
                        title= "SIF Time-Series (Select a county...)",
                        active_scroll = "wheel_zoom",
                        tooltips=[
                            ("Day", "@date"), 
                            ("Average SIF", "@sif")
                        ],
                        x_axis_label = 'Date',
                        y_axis_label = 'SIF Average',
                        y_range = (SIF_MIN, SIF_MAX))

    # Some font choices
    sif_series.title.text_font_size = '16pt'
    sif_series.xaxis.axis_label_text_font_size = "12pt"
    sif_series.yaxis.axis_label_text_font_size = "12pt"

    # Policy for hovering
    sif_series.hover.point_policy = "follow_mouse"

    # No logo
    sif_series.toolbar.logo = None

    # When a patch is selected, trigger the patch_time_series function
    p.on_event(Tap, patch_clicked)
    
    # On geometry selection
    lasso = LassoSelectTool(select_every_mousemove = False)
    p.add_tools(lasso)
    p.on_event(SelectionGeometry, shape_drawn)

    #################################
    # TODO: Set up download area
    #################################
    # def save_data():
    #     active_layer.save_data()
    #     print("Button Clicked")

    # callback = active_layer.get_save_data_js_callback()

    button = Button(label="Save Data", button_type="success")
    # button.on_click(active_layer.save_data)
    #button.js_on_event(ButtonClick, callback)

    #################################
    # Set up tab
    #################################

    # The layout of the view
    layout = row(column(p, date_range_slider, layer_selector), 
                 column(sif_series, row(column(), button)))

    # Create tab using layout
    tab = Panel(child=layout, title = 'US Visualization')

    # Return the created tab
    return tab
示例#20
0
def make_weight_graph(stock_name=None):
    """
    """
    try:
        API_URL = 'https://api.iextrading.com/1.0'
        res = requests.get(f'{ API_URL }/stock/{ stock_name }/chart/5y')
        data = res.json()
    except JSONDecodeError:
        abort(404)
    df = pd.DataFrame(data)
    # df['date'] = pd.to_datetime(df['date'])
    df['adjVolume'] = 6 * df['volume'] // df['volume'].mean()
    df = df[['date', 'vwap', 'volume', 'adjVolume']]
    seqs = np.arange(df.shape[0])
    df['seqs'] = pd.Series(seqs)

    source = ColumnDataSource(df)
    colors = [
        "#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1",
        "#cc7878", "#933b41", "#550b1d"
    ]
    mapper = LinearColorMapper(palette=colors,
                               low=df.adjVolume.min(),
                               high=df.adjVolume.max())

    hover = HoverTool(tooltips=[
        ('Date', '@date'),
        ('Vwap', '@vwap'),
        ('Volume', '@volume'),
    ],
                      names=["circle"])

    TOOLS = [
        hover,
        BoxZoomTool(),
        PanTool(),
        ZoomInTool(),
        ZoomOutTool(),
        ResetTool()
    ]
    p = figure(plot_width=1000,
               plot_height=800,
               title=f'5 year weighted performace of {stock_name}',
               tools=TOOLS,
               toolbar_location='above')

    p.circle(x="seqs",
             y="vwap",
             source=source,
             size='adjVolume',
             fill_color=transform('adjVolume', mapper),
             name="circle")
    color_bar = ColorBar(color_mapper=mapper,
                         location=(0, 0),
                         ticker=BasicTicker(desired_num_ticks=len(colors)),
                         formatter=PrintfTickFormatter(format="%s%%"))
    p.add_layout(color_bar, 'right')

    p.axis.axis_line_color = None
    p.axis.major_tick_line_color = None
    p.axis.major_label_text_font_size = "5pt"
    p.axis.major_label_standoff = 0
    p.xaxis.major_label_orientation = 1.0

    script, div = components(p)
    return script, div, stock_name
示例#21
0
def draw(S, position=None, with_labels=False):
    """Plot the given signed social network.

    Args:
        S: The network
        position (dict, optional):
            The position for the nodes. If no position is provided, a layout will be calculated. If the nodes have
            'color' attributes, a Kamanda-Kawai layout will be used to group nodes of the same color together.
            Otherwise, a circular layout will be used.

    Returns:
        A dictionary of positions keyed by node.

    Examples:
    >>> import dwave_structural_imbalance_demo as sbdemo
    >>> gssn = sbdemo.GlobalSignedSocialNetwork()
    >>> nld_before = gssn.get_node_link_data('Syria', 2013)
    >>> nld_after = gssn.solve_structural_imbalance('Syria', 2013)
    # draw Global graph before solving; save node layout for reuse
    >>> position = sbdemo.draw('syria.png', nld_before)
    # draw the Global graph; reusing the above layout, and calculating a new grouped layout
    >>> sbdemo.draw('syria_imbalance.png', nld_after, position)
    >>> sbdemo.draw('syria_imbalance_grouped', nld_after)

    """

    # we need a consistent ordering of the edges
    edgelist = S.edges()
    nodelist = S.nodes()

    def layout_wrapper(S):
        pos = position
        if pos is None:
            try:
                # group bipartition if nodes are colored
                dist = defaultdict(dict)
                for u, v in product(nodelist, repeat=2):
                    if u == v:  # node has no distance from itself
                        dist[u][v] = 0
                    elif nodelist[u]['color'] == nodelist[v]['color']:  # make same color nodes closer together
                        dist[u][v] = 1
                    else:  # make different color nodes further apart
                        dist[u][v] = 2
                pos = nx.kamada_kawai_layout(S, dist)
            except KeyError:
                # default to circular layout if nodes aren't colored
                pos = nx.circular_layout(S)
        return pos
    # call layout wrapper once with all nodes to store position for calls with partial graph
    position = layout_wrapper(S)

    plot = Plot(plot_width=600, plot_height=400, x_range=Range1d(-1.2, 1.2), y_range=Range1d(-1.2, 1.2))
    tools = [WheelZoomTool(), ZoomInTool(), ZoomOutTool(), PanTool()]
    plot.add_tools(*tools)
    plot.toolbar.active_scroll = tools[0]

    def get_graph_renderer(S, line_dash):
        # we need a consistent ordering of the edges
        edgelist = S.edges()
        nodelist = S.nodes()

        # get the colors assigned to each edge based on friendly/hostile
        sign_edge_color = ['#87DACD' if S[u][v]['sign'] == 1 else '#FC9291' for u, v in edgelist]

        # get the colors assigned to each node by coloring
        try:
            coloring_node_color = ['#4378F8' if nodelist[v]['color'] else '#FFE897' for v in nodelist]
        except KeyError:
            coloring_node_color = ['#FFFFFF' for __ in nodelist]

        graph_renderer = from_networkx(S, layout_wrapper)

        circle_size = 10
        graph_renderer.node_renderer.data_source.add(coloring_node_color, 'color')
        graph_renderer.node_renderer.glyph = Circle(size=circle_size, fill_color='color')

        edge_size = 2
        graph_renderer.edge_renderer.data_source.add(sign_edge_color, 'color')
        try:
            graph_renderer.edge_renderer.data_source.add([S[u][v]['event_year'] for u, v in edgelist], 'event_year')
            graph_renderer.edge_renderer.data_source.add(
                [S[u][v]['event_description'] for u, v in edgelist], 'event_description')
            plot.add_tools(HoverTool(tooltips=[("Year", "@event_year"), ("Description", "@event_description")],
                                    line_policy="interp"))
        except KeyError:
            pass
        graph_renderer.edge_renderer.glyph = MultiLine(line_color='color', line_dash=line_dash)

        graph_renderer.inspection_policy = EdgesAndLinkedNodes()

        return graph_renderer

    try:
        S_dash = S.edge_subgraph(((u, v) for u, v in edgelist if S[u][v]['frustrated']))
        S_solid = S.edge_subgraph(((u, v) for u, v in edgelist if not S[u][v]['frustrated']))
        plot.renderers.append(get_graph_renderer(S_dash, 'dashed'))
        plot.renderers.append(get_graph_renderer(S_solid, 'solid'))
    except KeyError:
        plot.renderers.append(get_graph_renderer(S, 'solid'))



    plot.background_fill_color = "#202239"

    positions = layout_wrapper(S)
    if with_labels:
        data = {
            'xpos': [],
            'ypos': [],
            'label': []
        }
        for label, pos in positions.items():
            data['label'].append(label)
            data['xpos'].append(pos[0])
            data['ypos'].append(pos[1])

        labels = LabelSet(x='xpos', y='ypos', text='label',
                        level='glyph', source=ColumnDataSource(data),
                        x_offset=-5, y_offset=10, text_color="#F5F7FB", text_font_size='12pt')
        plot.add_layout(labels)

    show(Row(plot))

    return positions
示例#22
0
def make_candle_chart(stock_name=None):
    """
    """

    try:
        API_URL = 'https://api.iextrading.com/1.0'
        res = requests.get(f'{ API_URL }/stock/{ stock_name }/chart/5y')
        data = res.json()
    except JSONDecodeError:
        abort(404)
    df = pd.DataFrame(data)
    # df["date"] = pd.to_datetime(df["date"])
    # import pdb; pdb.set_trace()
    seqs = np.arange(df.shape[0])
    df['seqs'] = pd.Series(seqs)
    df['changePercent'] = df['changePercent'].apply(lambda x: str(x) + '%')
    df['mid'] = df.apply(lambda x: (x['open'] + x['close']) / 2, axis=1)
    df['height'] = df.apply(lambda x: x['close'] - x['open']
                            if x['close'] != x['open'] else 0.01,
                            axis=1)
    inc = df.close > df.open
    dec = df.close < df.open
    w = .3
    sourceInc = bk.ColumnDataSource(df.loc[inc])
    sourceDec = bk.ColumnDataSource(df.loc[dec])

    hover = HoverTool(tooltips=[
        ('Date', '@date'),
        ('Low', '@low'),
        ('High', '@high'),
        ('Open', '@open'),
        ('Close', '@close'),
        ('Percent', '@changePercent'),
    ],
                      names=["rect1", "rect2"])

    TOOLS = [
        hover,
        BoxZoomTool(),
        PanTool(),
        ZoomInTool(),
        ZoomOutTool(),
        ResetTool()
    ]
    p = figure(plot_width=1000,
               plot_height=800,
               title=stock_name,
               tools=TOOLS,
               toolbar_location='above')
    p.xaxis.major_label_orientation = np.pi / 4
    p.grid.grid_line_alpha = w
    # descriptor = Label(x=70, y=70, text=f"5-year stock chart of {stock_name}")
    # p.add_layout(descriptor)

    p.segment(df.seqs[inc],
              df.high[inc],
              df.seqs[inc],
              df.low[inc],
              color='green')
    p.segment(df.seqs[dec],
              df.high[dec],
              df.seqs[dec],
              df.low[dec],
              color='red')

    p.rect(x='seqs',
           y='mid',
           width=w,
           height='height',
           fill_color='red',
           line_color='red',
           source=sourceDec,
           name="rect1")
    p.rect(x='seqs',
           y='mid',
           width=w,
           height='height',
           fill_color='green',
           line_color='green',
           source=sourceInc,
           name="rect2")

    script, div = components(p)
    return script, div, stock_name
    def plot_similarity(self, result, parameter):
        source1 = column_source(result, "FDA")
        source2 = column_source(result, "PPI")
        source3 = column_source(result, "MACRO")
        source4 = column_source(result, "NP")
        source5 = column_source(result, "FDA PEP")
        source6 = column_source(result, "linear")
        source7 = column_source(result, "cyclic")
        hover = HoverTool(tooltips=[
            ("sim", "$x"),
            ("CDF", "$y"),
        ])
        p = figure(
            title="CDF of Tanimoto Similarity, based on: " + parameter[0],
            x_axis_label="Similarity",
            y_axis_label="Cumulative Distribution Function",
            x_range=(0, 1),
            y_range=(0, 1),
            tools=[hover],
            plot_width=1000,
            plot_height=800,
        )
        p.add_tools(LassoSelectTool(), ZoomInTool(), ZoomOutTool(), SaveTool(),
                    PanTool())
        FDA_plot = p.line(x="x",
                          y="y",
                          source=source1,
                          color="darkslateblue",
                          line_width=3)
        PPI_plot = p.line(x="x",
                          y="y",
                          source=source2,
                          color="yellowgreen",
                          line_width=3)
        MACRO_plot = p.line(x="x",
                            y="y",
                            source=source3,
                            color="lightsteelblue",
                            line_width=3)
        NP_plot = p.line(x="x",
                         y="y",
                         source=source4,
                         color="olive",
                         line_width=3)
        PEP_FDA_plot = p.line(x="x",
                              y="y",
                              source=source5,
                              color="darkslategray",
                              line_width=3)
        LIN_plot = p.line(x="x",
                          y="y",
                          source=source6,
                          color="teal",
                          line_width=3)
        CYC_plot = p.line(x="x",
                          y="y",
                          source=source7,
                          color="mediumvioletred",
                          line_width=3)
        legend = Legend(
            items=[
                ("FDA", [FDA_plot]),
                ("PPI", [PPI_plot]),
                ("MACRO", [MACRO_plot]),
                ("NP", [NP_plot]),
                ("PEP FDA", [PEP_FDA_plot]),
                ("LIN", [LIN_plot]),
                ("CYC", [CYC_plot]),
            ],
            location="center",
            orientation="vertical",
            click_policy="hide",
        )
        p.add_layout(legend, place="right")
        p.xaxis.axis_label_text_font_size = "20pt"
        p.yaxis.axis_label_text_font_size = "20pt"
        p.xaxis.axis_label_text_color = "black"
        p.yaxis.axis_label_text_color = "black"
        p.xaxis.major_label_text_font_size = "18pt"
        p.yaxis.major_label_text_font_size = "18pt"
        p.title.text_font_size = "22pt"

        return p
示例#24
0
    def create(self, request, symbol=None):
        """
        """
        if not symbol:
            return Response(json='Company not found', status=404)

        url = f'https://api.iextrading.com/1.0/stock/{symbol}/chart/5y'
        data = requests.get(url)

        if not data:
            return Response(json='Invalid Company', status=404)

        import pdb
        pdb.set_trace()
        df = pd.DataFrame(data)
        seqs = np.arange(df.shape[0])

        df['seqs'] = pd.Series(seqs)
        df['changePercent'] = df['changePercent'].apply(lambda x: str(x) + '%')
        df['mid'] = df.apply(lambda x: (x['open'] + x['close']) / 2, axis=1)
        df['height'] = df.apply(lambda x: x['close'] - x['open']
                                if x['close'] != x['open'] else 0.001,
                                axis=1)

        inc = df.close > df.open
        dec = df.close < df.open
        w = .3

        sourceInc = bk.ColumnDataSource(df.loc[inc])
        sourceDec = bk.ColumnDataSource(df.loc[dec])

        hover = HoverTool(
            tooltips=[('date', '@date'), ('low', '@low'), (
                'high',
                '@high'), ('open',
                           '@open'), ('close',
                                      '@close'), ('percent',
                                                  '@changePercent')])
        TOOLS = [
            hover,
            BoxZoomTool(),
            PanTool(),
            ZoomInTool(),
            ZoomOutTool(),
            ResetTool()
        ]
        p = bk.figure(plot_width=1500,
                      plot_height=800,
                      tools=TOOLS,
                      title=f'{symbol}',
                      toolbar_location='above')

        p.xaxis.major_label_orientation = np.pi / 4
        p.grid.grid_line_alpha = w
        descriptor = Label(x=70, y=70, text='Past 5 years')
        p.add_layout(descriptor)

        p.segment(df.seqs[inc],
                  df.high[inc],
                  df.seqs[inc],
                  df.low[inc],
                  color='green')
        p.segment(df.seqs[dec],
                  df.high[dec],
                  df.seqs[dec],
                  df.low[dec],
                  color='red')

        p.rect(x='seqs',
               y='mid',
               width=w,
               height='height',
               fill_color='green',
               line_color='green',
               source=sourceInc)
        p.rect(x='seqs',
               y='mid',
               width=w,
               height='height',
               fill_color='red',
               line_color='red',
               source=sourceDec)

        bk.save(p,
                f'./static/{symbol}candle_stick.html',
                filename=f'5yr_candlestock')

        return Response(json='Data Created', status=200)
    def plot_tsne(self, parameter):
        result = self.result
        source1 = column_source(result, 'INACTIVO')
        source2 = column_source(result, 'PQSR-AGONISTA')
        source3 = column_source(result, 'RHLR-ANTAGONISTA')
        source4 = column_source(result, 'LASR-AGONISTA')
        source5 = column_source(result, 'PQSR-ANTAGONISTA')
        source6 = column_source(result, 'BIOFACQUIM_V2')
        source7 = column_source(result, 'LASR-ANTAGONISTA')
        source8 = column_source(result, 'QUIPRONAB')
        source9 = column_source(result, 'NuBBE')
        source10 = column_source(result, 'RHLR-AGONISTA')
        hover = HoverTool(tooltips=[
            ("PCA 1", "$x"),
            ("PCA 2", "$y"),
            ("NAME", "@N"),
        ])
        p = figure(
            title="tSNE based on " + parameter,
            x_axis_label="PC 1",
            y_axis_label="PC 2",
            x_range=(-7, 7),
            y_range=(-7, 7),
            tools=[hover],
            plot_width=1000,
            plot_height=800,
        )
        p.add_tools(LassoSelectTool(), ZoomInTool(), ZoomOutTool(), SaveTool(),
                    PanTool())

        INACTIVO_plot = p.circle(x="x",
                                 y="y",
                                 source=source1,
                                 color="indigo",
                                 size=5)
        PQSR_AGONISTA_plot = p.circle(x="x",
                                      y="y",
                                      source=source2,
                                      color="hotpink",
                                      size=5)
        RHLR_ANTAGONISTA_plot = p.circle(x="x",
                                         y="y",
                                         source=source3,
                                         color="navy",
                                         size=5)
        LASR_AGONISTA_plot = p.circle(x="x",
                                      y="y",
                                      source=source4,
                                      color="dodgerblue",
                                      size=5)
        PQSR_ANTAGONISTA_plot = p.circle(x="x",
                                         y="y",
                                         source=source5,
                                         color="lightcoral",
                                         size=5)
        BIOFACQUIM_V2_plot = p.circle(x="x",
                                      y="y",
                                      source=source6,
                                      color="gold",
                                      size=5)
        LASR_ANTAGONISTA_plot = p.circle(x="x",
                                         y="y",
                                         source=source7,
                                         color="yellowgreen",
                                         size=5)
        QUIPRONAB_plot = p.circle(x="x",
                                  y="y",
                                  source=source8,
                                  color="green",
                                  size=5)
        NuBBE_plot = p.circle(x="x",
                              y="y",
                              source=source9,
                              color="orangered",
                              size=5)
        RHLR_AGONISTA_plot = p.circle(x="x",
                                      y="y",
                                      source=source10,
                                      color="mediumvioletred",
                                      size=5)
        legend = Legend(
            items=[
                ('INACTIVO', [INACTIVO_plot]),
                ('PQSR-AGONISTA', [PQSR_AGONISTA_plot]),
                ('RHLR-ANTAGONISTA', [RHLR_ANTAGONISTA_plot]),
                ('LASR-AGONISTA', [LASR_AGONISTA_plot]),
                ('PQSR-ANTAGONISTA', [PQSR_ANTAGONISTA_plot]),
                ('BIOFACQUIM_V2', [BIOFACQUIM_V2_plot]),
                ('LASR-ANTAGONISTA', [LASR_ANTAGONISTA_plot]),
                ('QUIPRONAB', [QUIPRONAB_plot]),
                ('NuBBE', [NuBBE_plot]),
                ('RHLR-AGONISTA', [RHLR_AGONISTA_plot]),
            ],
            location="center",
            orientation="vertical",
            click_policy="hide",
        )
        p.add_layout(legend, place="right")
        p.xaxis.axis_label_text_font_size = "20pt"
        p.yaxis.axis_label_text_font_size = "20pt"
        p.xaxis.axis_label_text_color = "black"
        p.yaxis.axis_label_text_color = "black"
        p.xaxis.major_label_text_font_size = "18pt"
        p.yaxis.major_label_text_font_size = "18pt"
        p.title.text_font_size = "22pt"

        show(p)
def plotGeoPoints(data_dict,
                  data_title,
                  offset=0.25,
                  pt_size=7,
                  save_dir=None):
    if save_dir is not None:
        path = os.path.expanduser(save_dir)
        if os.path.exists(path) and os.path.isdir(path):
            os.chdir(path)
        else:
            print(
                "Warning: either {} does not exist or is not a valid directory; writing html file to {}"
                .format(path, os.getcwd()))
    noPunc = re.compile("[%s\\…]" % re.escape(string.punctuation))
    out_file_name = "{}.html".format(
        noPunc.sub("", data_title).replace(" ", "_"))
    ''' Plot the points collected from GeoMesa'''
    fid, x, y, what, who, when, why = zip(*[(key, row['x'], row['y'],
                                             row['what'], row['who'],
                                             row['when'], row['why'])
                                            for key, row in data_dict.items()])
    ''' Put the time fields into mm/dd/yyyy h:m am/pm format: '''
    when = [tm.strftime("%M/%d/%Y %I:%M %p") for tm in when]
    data_source = ColumnDataSource(
        dict(fid=fid, x=x, y=y, what=what, who=who, when=when, why=why))
    hover = HoverTool(tooltips=[
        ("fid", "@fid"),
        ("(x,y)", "($x, $y)"),
        ("Who", "@who"),
        ("What", "@what"),
        ("When", "@when"),
        ("Why", "@why"),
    ])
    tools = [
        PanTool(),
        BoxZoomTool(),
        CrosshairTool(), hover,
        WheelZoomTool(),
        ZoomInTool(),
        ZoomOutTool(),
        ResetTool(),
        SaveTool()
    ]
    ''' Set the values to show with hover: '''
    output_file(out_file_name, title="Results of {}".format(data_title))
    geo_plt = figure(title="GeoMesa--{}".format(data_title),
                     tools=tools,
                     plot_width=600,
                     plot_height=600)
    geo_plt.title.align = 'center'
    geo_plt.toolbar.logo = None
    geo_plt.toolbar_sticky = False
    geo_plt.xaxis.axis_label = "Lat"
    geo_plt.yaxis.axis_label = "Long"
    geo_plt.y_range = Range1d(start=min(y) - offset, end=max(y) + offset)
    geo_plt.x_range = Range1d(start=min(x) - offset, end=max(x) + offset)
    geo_plt.square("x",
                   "y",
                   fill_color="red",
                   line_color=None,
                   source=data_source,
                   size=pt_size)
    show(geo_plt)
    reset_output()
示例#27
0
def plot_bokeh(title):
	global topic_names, authors
	topic_names = grab_topics(t_model, feature_names, 5)

	x_ = []
	y_ = []
	t_ = []
	o_=[]
	topic_ = []

	global source
	source = ColumnDataSource(
			data =dict(
				x=x_,
				y=y_,
				t=t_,
				o=o_,
				desc=titles,
				topics=topic_,
				auth=authors,
				year=years
				))

	#Draw plots
	update_plot()
	

	global year_from, year_to, custom_text, search_text, radio_search, search_items, Keyword_text, custom_text1

	#Year filtering controls
	year_from = Slider(title="Include papers from", value=1981, start=1981, end=2017, step=1)

	year_to = Slider(title="Inlude papers to", value=2017, start=year_from.value-1, end=2017, step=1)
	year_from.on_change('value', update_years)
	year_to.on_change('value', update_years)
	now_change = Button(label="Update", button_type="success")
	now_change.on_click(update_plot)
	

	#Custom text placement controls
	#sizing_mode = 'scale_both' -- need to look for scaling the text box size
	#sizing_mode = 'stretch_both'
	
	custom_text = TextAreaInput(value=" ", title="Enter some text you are working on here:",width=600,height=400)
	text_button = Button(label="Process", button_type="success")
	# for i in custom_text.value:
	# 	if i == '.':
	# 		process_text()

	# 	callback1 = CustomJS( code="""
	# 	    // the event that triggered the callback is cb_obj:
	# // The event type determines the relevant attributes
	# console.log('Tap event occurred at x-position: ' + cb_obj.x)
	# """)
	
	# custom_text.on_change("value", my_text_input_handler)
	# custom_text.js_on_event('tap', callback1)
	# custom_text.on_event(MouseEnter, callback1)
	text_button.on_click(process_text)
	text_button.on_click(update_table)

	custom_text1 = TextAreaInput(value=" ", title="Enter text here if you want to search for individual words or lines:",width=600,height=200)
	text_button1 = Button(label="Process", button_type="success")
	text_button1.on_click(process_text1)
	text_button1.on_click(update_table)

	template200 = """
	<div style="font-size: 15px;">
	<%= value %>
	</div>
	"""
	
	keyword_data = ColumnDataSource(data ={})
	columns =[TableColumn(field ="keywords_", title ="<b> Keyword </b>", width = 700, formatter=HTMLTemplateFormatter(template=template200))]
	# Keyword_text = TextAreaInput(value ="default",title="Keywords", width = 800, height = 100)
	Keyword_text = DataTable(source=keyword_data, columns=columns, width=800, row_height=50, editable=True, fit_columns = True)

	Keyword_text.source.selected.on_change("indices", some_func)
	






	#Search button controls
	search_text = TextInput(value="", title="Search box: (separate terms with ';' - not for DOIs)")
	search_button = Button(label="Search", button_type="success")
	search_button.on_click(process_search)
	radio_search = RadioButtonGroup(labels=["Title", "Full Text", "doi","Author"], active=1)
	print("helllllll")
	#increase size
	#txtIn_rng = widgetbox(children=[custom_text], width=wd)
	#curdoc().add_root(txtIn_rng)


	#Data Table for selected papers
	
	global table_data, chosen_papers,dict2,table_row, table_cell_column_1, value1, value2, table_cell_column_2, summary3, dict4
	template = """<span href="#" data-toggle="tooltip" title="<%= value %>" style="font-size:15px"><%= value %></span>"""
	template_str = '<a href="http://dx.doi.org/<%=dois_%>" target="_blank"><%= value %></a>'



	# output_file("openurl.html")
	table_data = ColumnDataSource(data = {})
	print("***********")
	columns = [TableColumn(field="years_", title="<b>Year</b>",width = 50, formatter=HTMLTemplateFormatter(template=template)), TableColumn(field="titles_", title="<b>Paper Title</b>", width = 200, formatter=HTMLTemplateFormatter(template=template)), TableColumn(field="authors_", title="<b>Authors</b>", width = 100, formatter=HTMLTemplateFormatter(template=template)), TableColumn(field="dois_", title="<b>Link</b>",width = 100, formatter=HTMLTemplateFormatter(template=template_str)),TableColumn(field="summary_", title="<b>Summary</b>", width =600,formatter=HTMLTemplateFormatter(template=template))]
	print("1*")
	chosen_papers = DataTable(source=table_data, columns=columns, width=600, row_height=100, editable=True, fit_columns = True)

	table_row = TextInput(value = '', title = "Row index:")
	value1 =[]
	value2 = int(0)
	value3 =[]
	dict4 =[]
	table_cell_column_1 = TextAreaInput(value = '', title = "Papers from table", height = 100)
	table_cell_column_2 = TextAreaInput(value = '', title = "Papers from graph", height = 100)
	summary3 = TextAreaInput(value = '', title = "Summary of the recently selected paper", height = 300)
	# table_cell_column_2 = TextInput(value= '', title = "Author", height = 100)

	

	
	chosen_papers.source.selected.on_change('indices', function_source)


	# Adding a title for data table
	pre = Div(text="""Please hover over each column to see the full text. </br>
By clicking on each row, the desirable papers can be added to the 'Papers from table' list below.</br>
By clicking on authors column, authors can be directly placed in search.""",
width=600, height=50, style={'font-size': '100%', 'color': 'black', 'font-weight':'bold'})

# 	pre = PreText(text="""Please hover over each column to see the full text.\n
# By clicking on each row, the desirable papers can be added to the 'Papers from table' list below.\n
# By clicking on authors column, authors can be directly placed in search""",
# 	width=500, height=100)

	# Adding title for keyword data table
	pre1 = Div(text=""" If you click on keywords, the keyword will be directly placed in the 'Search Box' """, width=500, height=20,style={'font-size': '100%', 'color': 'black', 'font-weight':'bold'})







	# chosen_papers.append(HoverTool(tooltips=[("Summary", "@summary_")]))

	# para5 = Paragraph(text = 'summary' , height = 1)

	
	#chosen_papers.source.data.update(update_table())
	# chosen_papers.source.on_change('data', update_table1)


	# global table_data1, chosen_papers1
	# template = """<span href="#" data-toggle="tooltip" title="<%= value %>"><%= value %></span>"""

	# table_data1 = ColumnDataSource(data = {})
	# print("***********")
	# columns = [TableColumn(field="summary_", title="Summary", formatter=HTMLTemplateFormatter(template=template))]
	# print("1*")
	# chosen_papers1 = DataTable(source=table_data, columns=columns, width=800, row_height=100, editable=True,fit_columns = True, scroll_to_selection = True)

	
	# df = pd.DataFrame([
	# 	['this is a longer text that needs a tooltip, because otherwise we do not see the whole text', 'this is a short text'],
	# 	['this is another loooooooooooooooong text that needs a tooltip', 'not much here'],
	# ], columns=['a', 'b'])

	# columns = [TableColumn(field=c, title=c, width=20, formatter=HTMLTemplateFormatter(template=template)) for c in ['a', 'b']]

	# table = DataTable(source=ColumnDataSource(df), columns=columns)

	




	# create a new plot with a title and axis labels
	global patch, value6, value7
	p = figure(title="CHI scatter", tools="tap", x_axis_label='x', y_axis_label='y', width=800, plot_height=850)
	p.add_tools(BoxZoomTool())
	p.add_tools(ZoomInTool())
	p.add_tools(ZoomOutTool())
	p.add_tools(ResetTool())
	p.add_tools(HoverTool(tooltips=[("Title", "@desc"), ("Topic", "@topics"), ("Authors", "@auth"), ("Year", "@year")]))

	patch = p.circle(x='x', y='y', fill_color='t', nonselection_fill_color='t', radius=0.01, fill_alpha='o', nonselection_fill_alpha='o', line_color=None, source=source)
	url = "http://dx.doi.org/@dois"
	taptool = p.select(type=TapTool)
	taptool.callback = OpenURL(url=url)

	value6 = []
	value7 = []
	patch.data_source.on_change('selected', callback)

	p.on_event(Tap, callback1)



	l = gridplot([[ row([column(row([widgetbox(year_from, year_to, now_change), widgetbox(search_text, radio_search, search_button)]),widgetbox(custom_text, text_button), widgetbox(custom_text1, text_button1),widgetbox(pre,chosen_papers))]) ,column([p,widgetbox(pre1,Keyword_text)])  ],[table_cell_column_1], [table_cell_column_2], [summary3]   ])
	curdoc().add_root(l)
示例#28
0
def candlestick_chart(symbol):
    """To generate a candlestick chart of the chosen company."""

    url = f'https://api.iextrading.com/1.0/stock/{symbol}/chart/5y'

    res = req.get(url)

    data_5_year = res.json()

    df = pd.DataFrame(data_5_year)

    df['date_pd'] = pd.to_datetime(df.date)
    df['year'] = df.date_pd.dt.year

    year_num = df.year[int(len(df) - 1)] - df.year[3]

    if year_num >= 5:

        # 5 YEARS OF HISTORY IS AVAILABLE

        # PASS DATA INTO DATAFRAME
        seqs = np.arange(df.shape[0])
        df['seqs'] = pd.Series(seqs)

        df['mid'] = (df.high + df.low) // 2

        df['height'] = df.apply(lambda x: x['close'] - x['open']
                                if x['close'] != x['open'] else 0.01,
                                axis=1)

        inc = df.close > df.open
        dec = df.close < df.open
        w = .3

        sourceInc = bk.ColumnDataSource(df.loc[inc])
        sourceDec = bk.ColumnDataSource(df.loc[dec])

        hover = HoverTool(tooltips=[
            ('Date', '@date'),
            ('Low', '@low'),
            ('High', '@high'),
            ('Open', '@open'),
            ('Close', '@close'),
            ('Mid', '@mid'),
        ])

        TOOLS = [
            hover,
            BoxZoomTool(),
            PanTool(),
            ZoomInTool(),
            ZoomOutTool(),
            ResetTool()
        ]

        # PLOTTING THE CHART
        p = bk.figure(plot_width=600,
                      plot_height=450,
                      title=f'{symbol}',
                      tools=TOOLS,
                      toolbar_location='above')

        p.xaxis.major_label_orientation = np.pi / 4
        p.grid.grid_line_alpha = w
        descriptor = Label(x=180,
                           y=2000,
                           text='5-Year Data Of Your Chosen Company')
        p.add_layout(descriptor)

        # CHART LAYOUT
        p.segment(df.seqs[inc],
                  df.high[inc],
                  df.seqs[inc],
                  df.low[inc],
                  color='green')
        p.segment(df.seqs[dec],
                  df.high[dec],
                  df.seqs[dec],
                  df.low[dec],
                  color='red')
        p.rect(x='seqs',
               y='mid',
               width=w,
               height='height',
               fill_color='red',
               line_color='red',
               source=sourceDec)
        p.rect(x='seqs',
               y='mid',
               width=w,
               height='height',
               fill_color='green',
               line_color='green',
               source=sourceInc)

        script, div = components(p)

        return render_template("candlestick_chart.html",
                               the_div=div,
                               the_script=script)

    else:
        # 5-YEAR DATA IS NOT AVAILABLE
        flash('Company does not have a 5-year history.')
        return redirect(url_for('.portfolio_detail'))
示例#29
0
 def plot(self, source1, source2, source3, source4, source5, source6,
          source7, source8, source9):
     a = self.a
     b = self.b
     hover = HoverTool(tooltips=[
         ("PCA1", "($x)"),
         ("PCA2", "($y)"),
         ("NAME", "(@N)"),
     ])
     p = figure(title="CHEMICAL SPACE BY MORGAN2 FP",
                x_axis_label="PC 1 " + "(" + str(a) + "%)",
                y_axis_label="PC 2 " + "(" + str(b) + "%)",
                x_range=(-7, 7),
                y_range=(-7, 7),
                tools=[hover],
                plot_width=1000,
                plot_height=800)
     FDA_plot = p.circle(x="x",
                         y="y",
                         source=source1,
                         color="darkslateblue",
                         size=5)
     PPI_plot = p.circle(x="x",
                         y="y",
                         source=source2,
                         color="yellowgreen",
                         size=5)
     MACRO_plot = p.circle(x="x",
                           y="y",
                           source=source3,
                           color="lightsteelblue",
                           size=5)
     NP_plot = p.circle(x="x", y="y", source=source4, color="olive", size=5)
     PEP_FDA_plot = p.circle(x="x",
                             y="y",
                             source=source5,
                             color="darkslategray",
                             size=5)
     LIN_plot = p.circle(x="x",
                         y="y",
                         source=source6,
                         color="aquamarine",
                         size=5)
     LIN_NM_plot = p.circle(x="x",
                            y="y",
                            source=source7,
                            color="teal",
                            size=5)
     CYC_plot = p.circle(x="x",
                         y="y",
                         source=source8,
                         color="lightpink",
                         size=5)
     CYC_NM_plot = p.circle(x="x",
                            y="y",
                            source=source9,
                            color="mediumvioletred",
                            size=5)
     p.add_tools(LassoSelectTool(), ZoomInTool(), ZoomOutTool(), SaveTool(),
                 PanTool())
     legend = Legend(items=[
         ("FDA", [FDA_plot]),
         ("PPI", [PPI_plot]),
         ("MACRO", [MACRO_plot]),
         ("NP", [NP_plot]),
         ("PEP FDA", [PEP_FDA_plot]),
         ("LIN", [LIN_plot]),
         ("LIN NM", [LIN_NM_plot]),
         ("CYC", [CYC_plot]),
         ("CYC NM", [CYC_NM_plot]),
     ],
                     location="center",
                     orientation="vertical",
                     click_policy="hide")
     p.add_layout(legend, place='right')
     p.xaxis.axis_label_text_font_size = "20pt"
     p.yaxis.axis_label_text_font_size = "20pt"
     p.xaxis.axis_label_text_color = "black"
     p.yaxis.axis_label_text_color = "black"
     p.xaxis.major_label_text_font_size = "18pt"
     p.yaxis.major_label_text_font_size = "18pt"
     p.title.text_font_size = "22pt"
     return p
示例#30
0
def xrayvis_app(doc):
    def load_wav_cb(attr, old, new):
        '''Handle selection of audio file to be loaded.'''
        if new == '':
            return
        global wavname
        global snd
        spkr, fname = os.path.split(new)
        wavname = get_cached_fname(
            fname,
            f'https://linguistics.berkeley.edu/phonapps/xray_microbeam_database/{spkr}',
            spkr)
        #        wavname = new
        if not wavname.endswith('.wav'):
            return
        snd = parselmouth.Sound(wavname)
        srcdf = pd.DataFrame(
            dict(
                seconds=snd.ts().astype(np.float32),
                ch0=snd.values[0, :].astype(np.float32),
            ))
        #! TODO: do file caching
        phdf = allphdf.loc[allphdf.wavpath == new, :].copy()
        phdf['t1'] = phdf['t1'].astype(np.float32)
        wddf = allwddf.loc[allwddf.wavpath == new, :].copy()
        wddf['t1'] = wddf['t1'].astype(np.float32)
        uttdiv.text = '<b>Utterance:</b> ' + ' '.join(
            wddf.word.str.replace('sp', '')).strip()
        phwddf = pd.merge_asof(phdf[['t1', 'phone']],
                               wddf[['t1', 'word']],
                               on='t1',
                               suffixes=['_ph', '_wd'])
        # TODO: separate t1_ph and t1_wd columns
        srcdf = pd.merge_asof(srcdf, phwddf, left_on='seconds', right_on='t1')
        srcdf[['phone', 'word']] = srcdf[['phone', 'word']].fillna('')
        srcdf = srcdf.drop('t1', axis='columns')
        dfs['srcdf'] = srcdf
        source.data = srcdf
        tngsource.data = {'x': [], 'y': []}
        othsource.data = {'x': [], 'y': []}
        timesource.data = {k: [] for k in timesource.data.keys()}
        lasttngtimesource.data = {'x': [], 'y': []}
        lastothtimesource.data = {'x': [], 'y': []}
        playvisbtn.channels = channels
        playvisbtn.disabled = False
        playselbtn.channels = channels
        playselbtn.disabled = False
        playvisbtn.fs = snd.sampling_frequency
        playvisbtn.start = snd.start_time
        playvisbtn.end = snd.end_time
        playselbtn.fs = snd.sampling_frequency
        playselbtn.start = 0.0
        playselbtn.end = 0.0
        selbox.left = 0.0
        selbox.right = 0.0
        selbox.visible = False
        cursor.location = 0.0
        cursor.visible = False
        ch0.visible = True
        update_sgram()
        load_artic()
        set_limits(0.0, srcdf['seconds'].max())

    def load_artic():
        '''Load articulation data.'''
        trace.title.text = 'Static trace'
        traj.title.text = 'Trajectories'
        tngfile = os.path.splitext(wavname)[0] + '.txy'
        palfile = os.path.join(os.path.dirname(wavname), 'PAL.DAT')
        phafile = os.path.join(os.path.dirname(wavname), 'PHA.DAT')
        tngdf = pd.read_csv(tngfile,
                            sep='\t',
                            names=[
                                'sec', 'ULx', 'ULy', 'LLx', 'LLy', 'T1x',
                                'T1y', 'T2x', 'T2y', 'T3x', 'T3y', 'T4x',
                                'T4y', 'MIx', 'MIy', 'MMx', 'MMy'
                            ])
        # Convert to seconds
        tngdf['sec'] = tngdf['sec'] / 1e6
        tngdf = tngdf.set_index(['sec'])
        # Convert to mm
        tngdf[[
            'ULx', 'ULy', 'LLx', 'LLy', 'T1x', 'T1y', 'T2x', 'T2y', 'T3x',
            'T3y', 'T4x', 'T4y', 'MIx', 'MIy', 'MMx', 'MMy'
        ]] = tngdf[[
            'ULx', 'ULy', 'LLx', 'LLy', 'T1x', 'T1y', 'T2x', 'T2y', 'T3x',
            'T3y', 'T4x', 'T4y', 'MIx', 'MIy', 'MMx', 'MMy'
        ]] * 1e-3
        # Find global x/y max/min in this recording to set axis limits.
        # Exclude bad values (1000000 in data file; 1000 mm in scaled dataframe).
        cmpdf = tngdf[tngdf < badval]
        xmax = np.max(
            np.max(
                cmpdf[['ULx', 'LLx', 'T1x', 'T2x', 'T3x', 'T4x', 'MIx',
                       'MMx']]))
        xmin = np.min(
            np.min(
                cmpdf[['ULx', 'LLx', 'T1x', 'T2x', 'T3x', 'T4x', 'MIx',
                       'MMx']]))
        ymax = np.max(
            np.max(
                cmpdf[['ULy', 'LLy', 'T1y', 'T2y', 'T3y', 'T4y', 'MIy',
                       'MMy']]))
        ymin = np.min(
            np.min(
                cmpdf[['ULy', 'LLy', 'T1y', 'T2y', 'T3y', 'T4y', 'MIy',
                       'MMy']]))

        paldf = pd.read_csv(palfile, sep='\s+', header=None, names=['x', 'y'])
        paldf = paldf * 1e-3
        palsource.data = {'x': paldf['x'], 'y': paldf['y']}
        phadf = pd.read_csv(phafile, sep='\s+', header=None, names=['x', 'y'])
        phadf = phadf * 1e-3
        phasource.data = {'x': phadf['x'], 'y': phadf['y']}

        xmin = np.min([xmin, np.min(paldf['x']), np.min(phadf['x'])])
        xmax = np.max([xmax, np.max(paldf['x']), np.max(phadf['x'])])
        ymin = np.min([ymin, np.min(paldf['y']), np.min(phadf['y'])])
        ymax = np.max([ymax, np.max(paldf['y']), np.max(phadf['y'])])
        xsz = xmax - xmin
        ysz = ymax - ymin
        xrng = [xmin - (xsz * 0.05), xmax + (xsz * 0.05)]
        yrng = [ymin - (ysz * 0.05), ymax + (ysz * 0.05)]
        dfs['tngdf'] = tngdf
        dfs['paldf'] = paldf
        dfs['phadf'] = phadf

    def update_sgram():
        '''Update spectrogram based on current values.'''
        if snd.end_time < 15:
            sgrams[0] = snd2specgram(snd, 0.005)
            specsource.data = dict(
                sgram0=[sgrams[0].values.astype(np.float32)])
            spec0img.glyph.dw = sgrams[0].x_grid().max()
            spec0img.glyph.dh = sgrams[0].y_grid().max()
            spec0cmap.low = _low_thresh()
            spec0.visible = True
        else:
            specsource.data = dict(sgram0=[])
            spec0.visible = False

    def update_trace():
        '''Update the static trace at the cursor time.'''
        trace.title.text = f'Static trace ({cursor.location:0.4f})'
        tidx = dfs['tngdf'].index.get_loc(cursor.location, method='nearest')
        row = dfs['tngdf'].iloc[tidx]
        tngsource.data = {
            'x': [row.T1x, row.T2x, row.T3x, row.T4x],
            'y': [row.T1y, row.T2y, row.T3y, row.T4y]
        }
        othsource.data = {
            'x': [row.ULx, row.LLx, row.MIx, row.MMx],
            'y': [row.ULy, row.LLy, row.MIy, row.MMy]
        }

    def update_traj():
        '''Update the trajectories during the selected time range.'''
        traj.title.text = f'Trajectories ({selbox.left:0.4f} - {selbox.right:0.4f})'
        seldf = dfs['tngdf'].loc[(dfs['tngdf'].index >= selbox.left)
                                 & (dfs['tngdf'].index <= selbox.right)]
        dfs['seldf'] = seldf
        pts = ('T1x', 'T1y', 'T2x', 'T2y', 'T3x', 'T3y', 'T4x', 'T4y', 'ULx',
               'ULy', 'LLx', 'LLy', 'MIx', 'MIy', 'MMx', 'MMy')
        # Create a list of line segments for each tracked element.
        newdata = {
            pt: list(np.squeeze(np.dstack((seldf[pt].iloc[:-1], seldf[pt].iloc[1:])))) \
                for pt in pts
        }
        newdata['color'] = np.arange(1, len(seldf))
        newdata['sec'] = seldf.index[1:]
        timesource.data = newdata
        anim_slider.start = seldf.index[0]
        anim_slider.end = seldf.index[-1]
        anim_slider.step = np.diff(newdata['sec']).mean()
        anim_slider.value = anim_slider.end
        anim_slider.disabled = False
        anim_btn.disabled = False
        lastrow = seldf.iloc[-1]
        lasttngtimesource.data = {
            'x': [lastrow.T1x, lastrow.T2x, lastrow.T3x, lastrow.T4x],
            'y': [lastrow.T1y, lastrow.T2y, lastrow.T3y, lastrow.T4y]
        }
        lastothtimesource.data = {
            'x': [lastrow.ULx, lastrow.LLx, lastrow.MIx, lastrow.MMx],
            'y': [lastrow.ULy, lastrow.LLy, lastrow.MIy, lastrow.MMy]
        }

    # TODO: this is a workaround until we can set x_range, y_range directly
    # See https://github.com/bokeh/bokeh/issues/4014
    def set_limits(xstart, xend):
        '''Set axis limits.'''
        ch0.x_range.start = xstart
        ch0.x_range.end = xend
        ch0.axis[0].bounds = (xstart, xend)

    def update_select_widgets(clicked_x=None):
        '''Update widgets based on current selection. Use the clicked_x param to
        designate the cursor location if this function is called as the result of
        a Tap event. If clicked_x is None, then use the existing cursor location
        to set the center of the selection.'''
        mode = selmodebtn.labels[selmodebtn.active]
        if clicked_x is None and cursor.visible:
            x_loc = cursor.location
        elif clicked_x is not None:
            x_loc = clicked_x
        else:
            return
        if mode == '200ms':
            start = x_loc - 0.100
            end = x_loc + 0.100
            cursor.location = x_loc
        else:  # 'word' or 'phone'
            idx = np.abs(source.data['seconds'] - x_loc).argmin()
            # TODO: clean up the redundancy
            fld = {'word': 'word', 'phone': 'phone'}[mode]
            label = source.data[fld][idx]
            indexes = nonzero_groups(source.data[fld] == label,
                                     include_any=idx)
            secs = source.data['seconds'][indexes]
            start = secs.min()
            end = secs.max()
            cursor.location = secs.mean()
        playselbtn.start = start
        playselbtn.end = end
        selbox.left = start
        selbox.right = end
        selbox.visible = True
        cursor.visible = True

    def spkr_select_cb(attr, old, new):
        '''Respond to changes in speaker multiselect.'''
        try:
            spkrs = demo[
                (demo.sex.isin(sex_select.value) \
                & demo.dialect_base_state.isin(state_select.value) \
                & (demo.dialect_base_city.isin(city_select.value)))
            ].subject.unique()
            new_opts = [''] + [(f.value, f.label) for f in fileoptsdf[
                fileoptsdf.speaker.isin(spkrs)].itertuples()]
            fselect.options = new_opts
            fselect.value = ''
        except NameError as e:
            pass  # Values not set yet, so ignore

    def cursor_cb(e):
        '''Handle cursor mouse click in the waveform.'''
        update_select_widgets(clicked_x=e.x)
        update_trace()
        update_traj()

    def x_range_cb(attr, old, new):
        '''Handle change of x range in waveform/spectrogram.'''
        if attr == 'start':
            playvisbtn.start = new
        elif attr == 'end':
            playvisbtn.end = new

    def selection_cb(e):
        '''Handle data range selection event.'''
        #! TODO: handle situation in which selection is too short, i.e. len(seldf) <= 1
        cursor.location = (e.geometry['x0'] + e.geometry['x1']) / 2
        cursor.visible = True
        playselbtn.start = e.geometry['x0']
        playselbtn.end = e.geometry['x1']
        selbox.left = e.geometry['x0']
        selbox.right = e.geometry['x1']
        selbox.visible = True
        update_trace()
        update_traj()

    def selmode_cb(attr, old, new):
        '''Handle change in click selection value.'''
        update_select_widgets(clicked_x=None)

    def anim_cb(attr, old, new):
        '''Handle change in the animation slider.'''
        idx = np.argmin(np.abs(timesource.data['sec'] - new))
        n = len(timesource.data['color'])
        active = np.arange(n - idx, n + 1)
        timesource.data['color'] = np.pad(active, (0, n - len(active)),
                                          constant_values=0)
        anim_cmap = LinearColorMapper(palette=r_Greys256,
                                      low=1,
                                      high=n + 1,
                                      low_color='white')
        for tag, palette in (('anim_tng', r_Reds9), ('anim_oth', r_Greens9)):
            for a in find(traj.references(), {'tags': tag}):
                a.line_color = linear_cmap('color',
                                           palette,
                                           low=1,
                                           high=n + 1,
                                           low_color='white')
        lasttngtimesource.data = {
            'x': [
                timesource.data[pt][idx][1]
                for pt in ('T1x', 'T2x', 'T3x', 'T4x')
            ],
            'y': [
                timesource.data[pt][idx][1]
                for pt in ('T1y', 'T2y', 'T3y', 'T4y')
            ]
        }
        lastothtimesource.data = {
            'x': [
                timesource.data[pt][idx][1]
                for pt in ('ULx', 'LLx', 'MIx', 'MMx')
            ],
            'y': [
                timesource.data[pt][idx][1]
                for pt in ('ULy', 'LLy', 'MIy', 'MMy')
            ]
        }

    def anim_btn_cb():
        '''Handle click of anim_btn animate trajectories of selected audio.'''
        values = np.linspace(anim_slider.start, anim_slider.end,
                             len(timesource.data['T1x']))
        for v in values:
            anim_slider.value = v

    def low_thresh_cb(attr, old, new):
        '''Handle change in threshold slider to fade out low spectrogram values.'''
        params['low_thresh_power'] = new
        lt = _low_thresh()
        spec0cmap.low = lt

    def _low_thresh():
        return sgrams[0].values.min() \
               + sgrams[0].values.std()**params['low_thresh_power']

    step = None
    rate = orig_rate = None
    #    dfs = {}
    xrng = []
    yrng = []
    width = 1000
    height = 200
    cutoff = 50
    order = 3
    tngcolor = 'DarkRed'
    othcolor = 'Indigo'
    fselect = Select(options=[], value='')
    fselect.on_change('value', load_wav_cb)
    sex_select = MultiSelect(options=[('F', 'female'), ('M', 'male')],
                             value=['F', 'M'])
    state_select = MultiSelect(
        options=list(demo.dialect_base_state.cat.categories),
        value=list(demo.dialect_base_state.cat.categories))
    city_select = MultiSelect(
        options=list(demo.dialect_base_city.cat.categories),
        value=list(demo.dialect_base_city.cat.categories))
    sex_select.on_change('value', spkr_select_cb)
    state_select.on_change('value', spkr_select_cb)
    city_select.on_change('value', spkr_select_cb)
    spkr_select_cb('', '', '')

    source = ColumnDataSource(data=dict(seconds=[], ch0=[]))
    channels = ['ch0']

    playvisbtn = AudioButton(label='Play visible signal',
                             source=source,
                             channels=channels,
                             width=120,
                             disabled=True)
    playselbtn = AudioButton(label='Play selected signal',
                             source=source,
                             channels=channels,
                             width=120,
                             disabled=True)
    selmodebtn = RadioButtonGroup(labels=['200ms', 'word', 'phone'], active=1)
    selmodebtn.on_change('active', selmode_cb)
    # Instantiate and share specific select/zoom tools so that
    # highlighting is synchronized on all plots.
    boxsel = BoxSelectTool(dimensions='width')
    spboxsel = BoxSelectTool(dimensions='width')
    boxzoom = BoxZoomTool(dimensions='width')
    zoomin = ZoomInTool(dimensions='width')
    zoomout = ZoomOutTool(dimensions='width')
    crosshair = CrosshairTool(dimensions='height')
    shared_tools = [
        'xpan', boxzoom, boxsel, crosshair, zoomin, zoomout, 'reset'
    ]

    uttdiv = Div(text='')

    figargs = dict(tools=shared_tools, )
    cursor = Span(dimension='height',
                  line_color='red',
                  line_dash='dashed',
                  line_width=1)
    wavspec_height = 280
    ch0 = figure(name='ch0',
                 tooltips=[('time', '$x{0.0000}'), ('word', '@word'),
                           ('phone', '@phone')],
                 height=wavspec_height,
                 **figargs)
    ch0.toolbar.logo = None
    ch0.line(x='seconds', y='ch0', source=source, nonselection_line_alpha=0.6)
    # Link pan, zoom events for plots with x_range.
    ch0.x_range.on_change('start', x_range_cb)
    ch0.x_range.on_change('end', x_range_cb)
    ch0.on_event(SelectionGeometry, selection_cb)
    ch0.on_event(Tap, cursor_cb)
    ch0.add_layout(cursor)
    wavtab = Panel(child=ch0, title='Waveform')
    selbox = BoxAnnotation(name='selbox',
                           left=None,
                           right=None,
                           fill_color='green',
                           fill_alpha=0.1,
                           line_color='green',
                           line_width=1.5,
                           line_dash='dashed',
                           visible=False)
    ch0.add_layout(selbox)
    sgrams = [np.ones((1, 1))]
    specsource = ColumnDataSource(data=dict(sgram0=[sgrams[0]]))
    spec0 = figure(
        name='spec0',
        x_range=ch0.x_range,  # Keep times synchronized
        tooltips=[("time", "$x{0.0000}"), ("freq", "$y{0.0000}"),
                  ("value", "@sgram0{0.000000}")],
        height=wavspec_height,
        **figargs)
    spec0.toolbar.logo = None
    spec0.x_range.on_change('start', x_range_cb)
    spec0.x_range.on_change('end', x_range_cb)
    spec0.on_event(SelectionGeometry, selection_cb)
    spec0.on_event(Tap, cursor_cb)
    spec0.add_layout(cursor)
    spec0.x_range.range_padding = spec0.y_range.range_padding = 0
    spec0cmap = LogColorMapper(palette=r_Greys256,
                               low_color=params['low_thresh_color'])
    low_thresh_slider = Slider(start=1.0,
                               end=12.0,
                               step=0.03125,
                               value=params['low_thresh_power'],
                               title='Spectrogram threshold')
    low_thresh_slider.on_change('value', low_thresh_cb)
    spec0img = spec0.image(image='sgram0',
                           x=0,
                           y=0,
                           color_mapper=spec0cmap,
                           level='image',
                           source=specsource)
    spec0.grid.grid_line_width = 0.0
    spec0.add_layout(selbox)
    sgramtab = Panel(child=spec0, title='Spectrogram')

    tngsource = ColumnDataSource(data={'x': [], 'y': []})
    othsource = ColumnDataSource(data={'x': [], 'y': []})
    timesource = ColumnDataSource({
        'T1x': [],
        'T1y': [],
        'T2x': [],
        'T2y': [],
        'T3x': [],
        'T3y': [],
        'T4x': [],
        'T4y': [],
        'ULx': [],
        'ULy': [],
        'LLx': [],
        'LLy': [],
        'MIx': [],
        'MIy': [],
        'MMx': [],
        'MMy': [],
        'color': [],
        'sec': []
    })
    lasttngtimesource = ColumnDataSource(data={'x': [], 'y': []})
    lastothtimesource = ColumnDataSource(data={'x': [], 'y': []})
    palsource = ColumnDataSource(pd.DataFrame({'x': [], 'y': []}))
    phasource = ColumnDataSource(pd.DataFrame({'x': [], 'y': []}))

    trace = figure(width=500,
                   height=300,
                   title='Static trace',
                   x_range=(-100.0, 25.0),
                   y_range=(-37.650, 37.650),
                   tools=[],
                   tags=['xray', 'static_fig'])
    trace.toolbar.logo = None
    trace.circle('x',
                 'y',
                 source=tngsource,
                 size=3,
                 color=tngcolor,
                 tags=['update_xray'])
    trace.circle('x',
                 'y',
                 source=othsource,
                 size=3,
                 color=othcolor,
                 tags=['update_xray'])
    trace.line('x',
               'y',
               source=tngsource,
               color=tngcolor,
               tags=['update_xray'])
    trace.line('x', 'y', source=palsource, color='black')
    trace.line('x', 'y', source=phasource, color='black')

    traj = figure(width=500,
                  height=300,
                  title='Trajectories',
                  x_range=(-100.0, 25.0),
                  y_range=(-37.650, 37.650),
                  tools=[],
                  tags=['xray', 'trajectory_fig'])
    traj.toolbar.logo = None
    traj.multi_line('T1x', 'T1y', source=timesource, tags=['anim_tng'])
    traj.multi_line('T2x', 'T2y', source=timesource, tags=['anim_tng'])
    traj.multi_line('T3x', 'T3y', source=timesource, tags=['anim_tng'])
    traj.multi_line('T4x', 'T4y', source=timesource, tags=['anim_tng'])
    traj.multi_line('ULx', 'ULy', source=timesource, tags=['anim_oth'])
    traj.multi_line('LLx', 'LLy', source=timesource, tags=['anim_oth'])
    traj.multi_line('MIx', 'MIy', source=timesource, tags=['anim_oth'])
    traj.multi_line('MMx', 'MMy', source=timesource, tags=['anim_oth'])
    traj.circle('x', 'y', source=lasttngtimesource, color=tngcolor)
    traj.circle('x', 'y', source=lastothtimesource, color=othcolor)
    traj.line('x', 'y', source=lasttngtimesource, color='lightgray')
    traj.line('x', 'y', source=palsource, color='black')
    traj.line('x', 'y', source=phasource, color='black')

    anim_slider = Slider(start=0,
                         end=100,
                         step=1,
                         value=0,
                         width=240,
                         format='0.000f',
                         title='Selected trajectory',
                         orientation='horizontal',
                         disabled=True)
    anim_slider.on_change('value', anim_cb)
    anim_btn = Button(label='Animate', width=120, disabled=True)
    anim_btn.on_click(anim_btn_cb)

    audtabs = Tabs(tabs=[wavtab, sgramtab])
    mainLayout = column(
        row(sex_select, state_select, city_select),
        row(fselect),
        row(
            column(uttdiv, audtabs),
            column(
                #!                row(anim_slider, anim_btn),
                column(Div(text='Click selection mode:'), selmodebtn,
                       low_thresh_slider),
                row(playvisbtn, playselbtn))),
        row(trace, traj),
        name='mainLayout')
    doc.add_root(mainLayout)
    return doc