예제 #1
0
def add_legend(fig, labels, colors):
    """
    Add a legend to a figure given legend labels & colors.

    Parameters
    ----------
    fig : Bokeh Figure instance
        Figure instance labels should be generated for.
    labels : list of str
        Labels to use as legend entries.
    colors : Bokeh Palette instance
        Palette instance containing colours of choice.
    """
    from bokeh.models import Legend
    # add labels to figure (workaround,
    # legend with geojsondatasource doesn't work,
    # see https://github.com/bokeh/bokeh/issues/5904)
    items = []
    for label, color in zip(labels, colors):
        patch = fig.patches(xs=[], ys=[], fill_color=color)
        items.append((label, [patch]))

    legend = Legend(items=items, location='top_left', margin=0,
                    orientation='horizontal')
    # possibility to define glyph_width=10, glyph_height=10)
    legend.label_text_font_size = '8pt'
    fig.add_layout(legend, 'below')
    return legend
예제 #2
0
    def plot_legend(self, legend_items=None):
        """Add a legend to the plot.
        """
        if self._use_legend:
            from bokeh.models import Legend

            loc = {'best': 'top_left'}.get(self.legend_loc, self.legend_loc)
            where = {None: 'right'}.get(self.legend_where, self.legend_where)

            # might be manually specified, e.g. from multiplot
            if legend_items is None:
                legend_items = self._lgnd_items

            lg = Legend(items=legend_items)
            lg.location = loc
            lg.click_policy = 'hide'
            self._plot.add_layout(lg, where)

            # Don't repeatedly redraw legend
            self._use_legend = False
## plot-boundaries
displacement_range = Range1d(-40,40)
force_range = Range1d(-1.2,1.2)
time_range = Range1d(0,20)

##displacement-time diagram
displacementTime_plot = figure(title="",tools=["ywheel_zoom,xwheel_pan,pan,reset"],width = 400,height= 300,x_range  = time_range,
    y_range  = displacement_range)
displacementTime_plot.axis.axis_label_text_font_size="12pt"
displacementTime_plot.axis.axis_label_text_font_style="normal"
displacementTime_plot.yaxis.axis_label="Normalized Displacement u/(F/k₁)"
line_1 = displacementTime_plot.line(x='x',y='y', source = mainMass_displacementTime_source, color='#e37222')
line_2 = displacementTime_plot.line(x='x',y='y', source = topMass_displacementTime_source, color='#3070b3')
displacementTime_plot.toolbar.logo = None

legend = Legend(items=[(legend_text[0],[line_1]),(legend_text[1],[line_2])], location='top_right')
displacementTime_plot.add_layout(legend)

##force-time diagram
forceTime_plot = figure(title="",tools=["ywheel_zoom,xwheel_pan,pan,reset"],width = 400,height= 300,x_range  = time_range,
    y_range  = force_range)
forceTime_plot.axis.axis_label_text_font_size="12pt"
forceTime_plot.axis.axis_label_text_font_style="normal"
forceTime_plot.xaxis.axis_label="Time [s]"
forceTime_plot.yaxis.axis_label="Force [N]"
forceTime_plot.line(x='x',y='y', source = forceTime_source, color='black')
forceTime_plot.toolbar.logo = None


################################################################################
#Add application describtion
예제 #4
0
def _display_timeline_dict(data: dict,
                           **kwargs) -> figure:  # noqa: C901, MC0001
    """
    Display a timeline of events.

    Parameters
    ----------
    data : dict
        Data points to plot on the timeline.
            Need to contain:
                Key - Name of data type to be displayed in legend
                Value - dict of data containing:
                    data : pd.DataFrame
                        Data to plot
                    time_column : str
                        Name of the timestamp column
                    source_columns : list
                        List of source columns to use in tooltips
                    color: str
                        Color of datapoints for this data
    Other Parameters
    ----------------
    ref_time : datetime, optional
        Input reference line to display (the default is None)
    title : str, optional
        Title to display (the default is None)
    time_column : str, optional
        Name of the timestamp column
        (the default is 'TimeGenerated')
    legend: str, optional
        Where to position the legend
        None, left, right or inline (default is None)
    yaxis : bool, optional
        Whether to show the yaxis and labels
    range_tool : bool, optional
        Show the the range slider tool (default is True)
    source_columns : list, optional
        List of default source columns to use in tooltips
        (the default is None)
    height : int, optional
        The height of the plot figure
        (the default is auto-calculated height)
    width : int, optional
        The width of the plot figure (the default is 900)

    Returns
    -------
    figure
        The bokeh plot figure.

    """
    reset_output()
    output_notebook()

    height: int = kwargs.pop("height", None)
    width: int = kwargs.pop("width", 900)
    ref_time: Any = kwargs.pop("ref_time", None)
    ref_label: str = kwargs.pop("ref_label", None)
    title: str = kwargs.pop("title", None)
    legend_pos: str = kwargs.pop("legend", None)
    show_yaxis: bool = kwargs.pop("yaxis", False)
    show_range: bool = kwargs.pop("range_tool", True)
    xgrid: bool = kwargs.pop("xgrid", True)
    ygrid: bool = kwargs.pop("ygrid", False)

    tool_tip_columns, min_time, max_time = _unpack_data_series_dict(
        data, **kwargs)
    series_count = len(data)

    # build the tool tips from all specified columns
    tool_tip_items = [(f"{col}", f"@{col}") for col in tool_tip_columns]
    hover = HoverTool(tooltips=tool_tip_items,
                      formatters={"Tooltip": "printf"})

    title = f"Timeline: {title}" if title else "Event Timeline"
    start_range = min_time - ((max_time - min_time) * 0.1)
    end_range = max_time + ((max_time - min_time) * 0.1)
    height = height if height else _calc_auto_plot_height(len(data))
    y_range = ((-1 / series_count), series_count - 1 + (1 / series_count))
    plot = figure(
        x_range=(start_range, end_range),
        y_range=y_range,
        min_border_left=50,
        plot_height=height,
        plot_width=width,
        x_axis_label="Event Time",
        x_axis_type="datetime",
        x_minor_ticks=10,
        tools=[hover, "xwheel_zoom", "box_zoom", "reset", "save", "xpan"],
        title=title,
    )
    plot.yaxis.visible = show_yaxis
    if show_yaxis:
        if data:
            y_labels = {
                ser_def["y_index"]: str(lbl)
                for lbl, ser_def in data.items()
            }
            plot.yaxis.major_label_overrides = y_labels
    if ygrid:
        plot.ygrid.minor_grid_line_color = "navy"
        plot.ygrid.minor_grid_line_alpha = 0.1
        plot.ygrid.grid_line_color = "navy"
        plot.ygrid.grid_line_alpha = 0.3
    else:
        plot.ygrid.grid_line_color = None
    if xgrid:
        plot.xgrid.minor_grid_line_color = "navy"
        plot.xgrid.minor_grid_line_alpha = 0.3
    else:
        plot.xgrid.grid_line_color = None

    # Create plot bar to act as as range selector
    rng_select = _create_range_tool(
        data=data,
        min_time=min_time,
        max_time=max_time,
        plot_range=plot.x_range,
        width=width,
        height=height,
    )

    # set the tick datetime formatter
    plot.xaxis[0].formatter = _get_tick_formatter()

    if series_count > 1 and not legend_pos:
        legend_pos = "left"

    # plot groups individually so that we can create an interactive legend
    # if legend_pos is "inline", we add add the normal legend inside the plot
    # if legend_pos is "left" or "right", we add the legend to the side
    legend_items = []
    for ser_name, series_def in data.items():
        inline_legend = ser_name if legend_pos == "inline" else None
        p_series = plot.diamond(
            x=series_def["time_column"],
            y="y_index",
            color=series_def["color"],
            alpha=0.5,
            size=10,
            source=series_def["source"],
            legend=inline_legend,
        )
        if legend_pos in ["left", "right"]:
            legend_items.append((str(ser_name), [p_series]))

    if legend_pos == "inline":
        # Position the inline legend
        plot.legend.location = "center_left"
        plot.legend.click_policy = "hide"
    elif legend_pos in ["left", "right"]:
        # Create the legend box outside of the plot area
        ext_legend = Legend(
            items=legend_items,
            location="center",
            click_policy="hide",
            label_text_font_size="8pt",
        )
        plot.add_layout(ext_legend, legend_pos)

    if ref_time is not None:
        _add_ref_line(plot, ref_time, ref_label, len(data))

    if show_range:
        show(column(plot, rng_select))
    else:
        show(plot)
    return plot
예제 #5
0
def plotspectra(spectra,
                zcatalog=None,
                model=None,
                notebook=False,
                title=None):
    '''
    TODO: document
    '''

    if notebook:
        bk.output_notebook()

    #- If inputs are frames, convert to a spectra object
    if isinstance(spectra, list) and isinstance(spectra[0],
                                                desispec.frame.Frame):
        spectra = frames2spectra(spectra)
        frame_input = True
    else:
        frame_input = False

    if frame_input and title is None:
        meta = spectra.meta
        title = 'Night {} ExpID {} Spectrograph {}'.format(
            meta['NIGHT'],
            meta['EXPID'],
            meta['CAMERA'][1],
        )

    #- Gather spectra into ColumnDataSource objects for Bokeh
    nspec = spectra.num_spectra()
    cds_spectra = list()

    for band in spectra.bands:
        #- Set masked bins to NaN so that Bokeh won't plot them
        bad = (spectra.ivar[band] == 0.0) | (spectra.mask[band] != 0)
        spectra.flux[band][bad] = np.nan

        cdsdata = dict(
            origwave=spectra.wave[band].copy(),
            plotwave=spectra.wave[band].copy(),
        )

        for i in range(nspec):
            key = 'origflux' + str(i)
            cdsdata[key] = spectra.flux[band][i]

        cdsdata['plotflux'] = cdsdata['origflux0']

        cds_spectra.append(bk.ColumnDataSource(cdsdata, name=band))

    #- Reorder zcatalog to match input targets
    #- TODO: allow more than one zcatalog entry with different ZNUM per targetid
    targetids = spectra.target_ids()
    if zcatalog is not None:
        ii = np.argsort(np.argsort(targetids))
        jj = np.argsort(zcatalog['TARGETID'])
        kk = jj[ii]
        zcatalog = zcatalog[kk]

        #- That sequence of argsorts may feel like magic,
        #- so make sure we got it right
        assert np.all(zcatalog['TARGETID'] == targetids)
        assert np.all(zcatalog['TARGETID'] == spectra.fibermap['TARGETID'])

        #- Also need to re-order input model fluxes
        if model is not None:
            mwave, mflux = model
            model = mwave, mflux[kk]

    #- Gather models into ColumnDataSource objects, row matched to spectra
    if model is not None:
        mwave, mflux = model
        model_obswave = mwave.copy()
        model_restwave = mwave.copy()
        cds_model_data = dict(
            origwave=mwave.copy(),
            plotwave=mwave.copy(),
            plotflux=np.zeros(len(mwave)),
        )

        for i in range(nspec):
            key = 'origflux' + str(i)
            cds_model_data[key] = mflux[i]

        cds_model_data['plotflux'] = cds_model_data['origflux0']
        cds_model = bk.ColumnDataSource(cds_model_data)
    else:
        cds_model = None

    #- Subset of zcatalog and fibermap columns into ColumnDataSource
    target_info = list()
    for i, row in enumerate(spectra.fibermap):
        target_bit_names = ' '.join(desi_mask.names(row['DESI_TARGET']))
        txt = 'Target {}: {}'.format(row['TARGETID'], target_bit_names)
        if zcatalog is not None:
            txt += '<BR/>{} z={:.4f} ± {:.4f}  ZWARN={}'.format(
                zcatalog['SPECTYPE'][i],
                zcatalog['Z'][i],
                zcatalog['ZERR'][i],
                zcatalog['ZWARN'][i],
            )
        target_info.append(txt)

    cds_targetinfo = bk.ColumnDataSource(dict(target_info=target_info),
                                         name='targetinfo')
    if zcatalog is not None:
        cds_targetinfo.add(zcatalog['Z'], name='z')

    plot_width = 800
    plot_height = 400
    # tools = 'pan,box_zoom,wheel_zoom,undo,redo,reset,save'
    tools = 'pan,box_zoom,wheel_zoom,reset,save'
    fig = bk.figure(height=plot_height,
                    width=plot_width,
                    title=title,
                    tools=tools,
                    toolbar_location='above',
                    y_range=(-10, 20))
    fig.toolbar.active_drag = fig.tools[1]  #- box zoom
    fig.toolbar.active_scroll = fig.tools[2]  #- wheel zoom
    fig.xaxis.axis_label = 'Wavelength [Å]'
    fig.yaxis.axis_label = 'Flux'
    fig.xaxis.axis_label_text_font_style = 'normal'
    fig.yaxis.axis_label_text_font_style = 'normal'
    colors = dict(b='#1f77b4', r='#d62728', z='maroon')

    data_lines = list()
    for spec in cds_spectra:
        lx = fig.line('plotwave',
                      'plotflux',
                      source=spec,
                      line_color=colors[spec.name])
        data_lines.append(lx)

    if cds_model is not None:
        model_lines = list()
        lx = fig.line('plotwave',
                      'plotflux',
                      source=cds_model,
                      line_color='black')
        model_lines.append(lx)

        legend = Legend(items=[
            ("data",
             data_lines[-1::-1]),  #- reversed to get blue as lengend entry
            ("model", model_lines),
        ])
    else:
        legend = Legend(items=[
            ("data",
             data_lines[-1::-1]),  #- reversed to get blue as lengend entry
        ])

    fig.add_layout(legend, 'center')
    fig.legend.click_policy = 'hide'  #- or 'mute'

    #- Zoom figure around mouse hover of main plot
    zoomfig = bk.figure(
        height=plot_height // 2,
        width=plot_height // 2,
        y_range=fig.y_range,
        x_range=(5000, 5100),
        # output_backend="webgl",
        toolbar_location=None,
        tools=[])

    for spec in cds_spectra:
        zoomfig.line('plotwave',
                     'plotflux',
                     source=spec,
                     line_color=colors[spec.name],
                     line_width=1,
                     line_alpha=1.0)

    if cds_model is not None:
        zoomfig.line('plotwave',
                     'plotflux',
                     source=cds_model,
                     line_color='black')

    #- Callback to update zoom window x-range
    zoom_callback = CustomJS(args=dict(zoomfig=zoomfig),
                             code="""
            zoomfig.x_range.start = cb_obj.x - 100;
            zoomfig.x_range.end = cb_obj.x + 100;
        """)

    fig.js_on_event(bokeh.events.MouseMove, zoom_callback)

    #-----
    #- Emission and absorption lines
    z = zcatalog['Z'][0] if (zcatalog is not None) else 0.0
    line_data, lines, line_labels = add_lines(fig, z=z)

    #-----
    #- Add widgets for controling plots
    z1 = np.floor(z * 100) / 100
    dz = z - z1
    zslider = Slider(start=0.0, end=4.0, value=z1, step=0.01, title='Redshift')
    dzslider = Slider(start=0.0,
                      end=0.01,
                      value=dz,
                      step=0.0001,
                      title='+ Delta redshift')
    dzslider.format = "0[.]0000"

    #- Observer vs. Rest frame wavelengths
    waveframe_buttons = RadioButtonGroup(labels=["Obs", "Rest"], active=0)

    ifiberslider = Slider(start=0, end=nspec - 1, value=0, step=1)
    if frame_input:
        ifiberslider.title = 'Fiber'
    else:
        ifiberslider.title = 'Target'

    zslider_callback = CustomJS(
        args=dict(
            spectra=cds_spectra,
            model=cds_model,
            targetinfo=cds_targetinfo,
            ifiberslider=ifiberslider,
            zslider=zslider,
            dzslider=dzslider,
            waveframe_buttons=waveframe_buttons,
            line_data=line_data,
            lines=lines,
            line_labels=line_labels,
            fig=fig,
        ),
        #- TODO: reorder to reduce duplicated code
        code="""
        var z = zslider.value + dzslider.value
        var line_restwave = line_data.data['restwave']
        var ifiber = ifiberslider.value
        var zfit = 0.0
        if(targetinfo.data['z'] != undefined) {
            zfit = targetinfo.data['z'][ifiber]
        }

        // Observer Frame
        if(waveframe_buttons.active == 0) {
            var x = 0.0
            for(var i=0; i<line_restwave.length; i++) {
                x = line_restwave[i] * (1+z)
                lines[i].location = x
                line_labels[i].x = x
            }
            for(var i=0; i<spectra.length; i++) {
                var data = spectra[i].data
                var origwave = data['origwave']
                var plotwave = data['plotwave']
                for (var j=0; j<plotwave.length; j++) {
                    plotwave[j] = origwave[j]
                }
                spectra[i].change.emit()
            }

            // Update model wavelength array
            if(model) {
                var origwave = model.data['origwave']
                var plotwave = model.data['plotwave']
                for(var i=0; i<plotwave.length; i++) {
                    plotwave[i] = origwave[i] * (1+z) / (1+zfit)
                }
                model.change.emit()
            }

        // Rest Frame
        } else {
            for(i=0; i<line_restwave.length; i++) {
                lines[i].location = line_restwave[i]
                line_labels[i].x = line_restwave[i]
            }
            for (var i=0; i<spectra.length; i++) {
                var data = spectra[i].data
                var origwave = data['origwave']
                var plotwave = data['plotwave']
                for (var j=0; j<plotwave.length; j++) {
                    plotwave[j] = origwave[j] / (1+z)
                }
                spectra[i].change.emit()
            }

            // Update model wavelength array
            if(model) {
                var origwave = model.data['origwave']
                var plotwave = model.data['plotwave']
                for(var i=0; i<plotwave.length; i++) {
                    plotwave[i] = origwave[i] / (1+zfit)
                }
                model.change.emit()
            }
        }
        """)

    zslider.js_on_change('value', zslider_callback)
    dzslider.js_on_change('value', zslider_callback)
    waveframe_buttons.js_on_click(zslider_callback)

    plotrange_callback = CustomJS(args=dict(
        zslider=zslider,
        dzslider=dzslider,
        waveframe_buttons=waveframe_buttons,
        fig=fig,
    ),
                                  code="""
        var z = zslider.value + dzslider.value
        // Observer Frame
        if(waveframe_buttons.active == 0) {
            fig.x_range.start = fig.x_range.start * (1+z)
            fig.x_range.end = fig.x_range.end * (1+z)
        } else {
            fig.x_range.start = fig.x_range.start / (1+z)
            fig.x_range.end = fig.x_range.end / (1+z)
        }
        """)
    waveframe_buttons.js_on_click(plotrange_callback)

    smootherslider = Slider(start=0,
                            end=31,
                            value=0,
                            step=1.0,
                            title='Gaussian Sigma Smooth')
    target_info_div = Div(text=target_info[0])

    #-----
    #- Toggle lines
    lines_button_group = CheckboxButtonGroup(labels=["Emission", "Absorption"],
                                             active=[])

    lines_callback = CustomJS(args=dict(line_data=line_data,
                                        lines=lines,
                                        line_labels=line_labels),
                              code="""
        var show_emission = false
        var show_absorption = false
        if (cb_obj.active.indexOf(0) >= 0) {  // index 0=Emission in active list
            show_emission = true
        }
        if (cb_obj.active.indexOf(1) >= 0) {  // index 1=Absorption in active list
            show_absorption = true
        }

        for(var i=0; i<lines.length; i++) {
            if(line_data.data['emission'][i]) {
                lines[i].visible = show_emission
                line_labels[i].visible = show_emission
            } else {
                lines[i].visible = show_absorption
                line_labels[i].visible = show_absorption
            }
        }
        """)
    lines_button_group.js_on_click(lines_callback)
    # lines_button_group.js_on_change('value', lines_callback)

    #-----
    update_plot = CustomJS(args=dict(
        spectra=cds_spectra,
        model=cds_model,
        targetinfo=cds_targetinfo,
        target_info_div=target_info_div,
        ifiberslider=ifiberslider,
        smootherslider=smootherslider,
        zslider=zslider,
        dzslider=dzslider,
        lines_button_group=lines_button_group,
        fig=fig,
    ),
                           code="""
        var ifiber = ifiberslider.value
        var nsmooth = smootherslider.value
        target_info_div.text = targetinfo.data['target_info'][ifiber]

        if(targetinfo.data['z'] != undefined) {
            var z = targetinfo.data['z'][ifiber]
            var z1 = Math.floor(z*100) / 100
            zslider.value = z1
            dzslider.value = (z - z1)
        }

        function get_y_minmax(pmin, pmax, data) {
            // copy before sorting to not impact original, and filter out NaN
            var dx = data.slice().filter(Boolean)
            dx.sort()
            var imin = Math.floor(pmin * dx.length)
            var imax = Math.floor(pmax * dx.length)
            return [dx[imin], dx[imax]]
        }

        // Smoothing kernel
        var kernel = [];
        for(var i=-2*nsmooth; i<=2*nsmooth; i++) {
            kernel.push(Math.exp(-(i**2)/(2*nsmooth)))
        }
        var kernel_offset = Math.floor(kernel.length/2)

        // Smooth plot and recalculate ymin/ymax
        // TODO: add smoother function to reduce duplicated code
        var ymin = 0.0
        var ymax = 0.0
        for (var i=0; i<spectra.length; i++) {
            var data = spectra[i].data
            var plotflux = data['plotflux']
            var origflux = data['origflux'+ifiber]
            for (var j=0; j<plotflux.length; j++) {
                if(nsmooth == 0) {
                    plotflux[j] = origflux[j]
                } else {
                    plotflux[j] = 0.0
                    var weight = 0.0
                    // TODO: speed could be improved by moving `if` out of loop
                    for (var k=0; k<kernel.length; k++) {
                        var m = j+k-kernel_offset
                        if((m >= 0) && (m < plotflux.length)) {
                            var fx = origflux[m]
                            if(fx == fx) {
                                plotflux[j] = plotflux[j] + fx * kernel[k]
                                weight += kernel[k]
                            }
                        }
                    }
                    plotflux[j] = plotflux[j] / weight
                }
            }
            spectra[i].change.emit()

            tmp = get_y_minmax(0.01, 0.99, plotflux)
            ymin = Math.min(ymin, tmp[0])
            ymax = Math.max(ymax, tmp[1])
        }

        // update model
        if(model) {
            var plotflux = model.data['plotflux']
            var origflux = model.data['origflux'+ifiber]
            for (var j=0; j<plotflux.length; j++) {
                if(nsmooth == 0) {
                    plotflux[j] = origflux[j]
                } else {
                    plotflux[j] = 0.0
                    var weight = 0.0
                    // TODO: speed could be improved by moving `if` out of loop
                    for (var k=0; k<kernel.length; k++) {
                        var m = j+k-kernel_offset
                        if((m >= 0) && (m < plotflux.length)) {
                            var fx = origflux[m]
                            if(fx == fx) {
                                plotflux[j] = plotflux[j] + fx * kernel[k]
                                weight += kernel[k]
                            }
                        }
                    }
                    plotflux[j] = plotflux[j] / weight
                }
            }
            model.change.emit()
        }

        // update y_range
        if(ymin<0) {
            fig.y_range.start = ymin * 1.4
        } else {
            fig.y_range.start = ymin * 0.6
        }
        fig.y_range.end = ymax * 1.4
    """)
    smootherslider.js_on_change('value', update_plot)
    ifiberslider.js_on_change('value', update_plot)

    #-----
    #- Add navigation buttons
    navigation_button_width = 30
    prev_button = Button(label="<", width=navigation_button_width)
    next_button = Button(label=">", width=navigation_button_width)

    prev_callback = CustomJS(args=dict(ifiberslider=ifiberslider),
                             code="""
        if(ifiberslider.value>0) {
            ifiberslider.value--
        }
        """)
    next_callback = CustomJS(args=dict(ifiberslider=ifiberslider, nspec=nspec),
                             code="""
        if(ifiberslider.value<nspec+1) {
            ifiberslider.value++
        }
        """)

    prev_button.js_on_event('button_click', prev_callback)
    next_button.js_on_event('button_click', next_callback)

    #-----
    slider_width = plot_width - 2 * navigation_button_width
    navigator = bk.Row(
        widgetbox(prev_button, width=navigation_button_width),
        widgetbox(next_button, width=navigation_button_width + 20),
        widgetbox(ifiberslider, width=slider_width - 20))
    bk.show(
        bk.Column(
            bk.Row(fig, zoomfig),
            widgetbox(target_info_div, width=plot_width),
            navigator,
            widgetbox(smootherslider, width=plot_width // 2),
            bk.Row(
                widgetbox(waveframe_buttons, width=120),
                widgetbox(zslider, width=plot_width // 2 - 60),
                widgetbox(dzslider, width=plot_width // 2 - 60),
            ),
            widgetbox(lines_button_group),
        ))
               renderers=[glyphs[missions.index(ii)]]) for ii in bottomleg
]
items3 = [
    LegendItem(label=ii + f' ({counts[missions.index(ii)]})',
               renderers=[glyphs[missions.index(ii)]]) for ii in vbottomleg
]

# create the two legends
for ii in np.arange(3):
    if ii == 0:
        items = items3
    elif ii == 1:
        items = items2
    else:
        items = items1
    legend = Legend(items=items, location="center")

    if ii == 2:
        legend.title = 'Discovered by and Status'
        legend.spacing = 10
    else:
        legend.spacing = 11

    legend.location = (-70, 5)
    legend.label_text_align = 'left'
    legend.margin = 0

    fig.add_layout(legend, 'above')

# overall figure title
fig.title.text = 'Transiting Planets and Planet Candidates'
예제 #7
0
def plot_data(df, dsn):
    '''Plot the data in the given dataframe

    Parameters:
        df        (dataframe) - data from the given dsn
        dsn       (str) - device identifier

    '''
    names = [
        "heart_rate_avg", "oxygen_avg", "skin_temperature", "base_state",
        "movement_raw"
    ]
    colors = ["blue", "orange", "red", "purple", "green"]
    alphas = [.8, 8, .8, .7, .6]

    # Where data is stored so it can be displayed and changed dynamically
    source_data, source_data1, source_data2, source_data3, source_data4, source_data5, min_val, max_hr = get_source(
        df, names)

    # Multiple sources because there are different lengths of data
    source = ColumnDataSource(data=source_data)
    source1 = ColumnDataSource(data=source_data1)
    source2 = ColumnDataSource(data=source_data2)
    source3 = ColumnDataSource(data=source_data3)
    source4 = ColumnDataSource(data=source_data4)
    source5 = ColumnDataSource(data=source_data5)

    # Build plot tools
    hover_tool = HoverTool(
        tooltips=[
            ('time', '@date{%T}'),
        ] + [(name, '@{}'.format(name)) for name in names] +
        [('notification', '@notification_mask')],  #data: good; corrupt
        formatters={
            'date': 'datetime',
        },  # use default 'numeral' formatter for other fields
        mode='vline',
        renderers=[])
    crosshair = CrosshairTool(dimensions='height', line_alpha=.6)
    box_zoom = BoxZoomTool(dimensions='width')
    zoom_out = ZoomOutTool(dimensions='width', factor=.5)
    save = CustomSaveTool(save_name=dsn)

    x_range_start = df.timestamp.min() - timedelta(minutes=30)
    x_range_end = df.timestamp.max() + timedelta(minutes=30)

    # Create figure; use webgl for better rendering
    tools = [save, box_zoom, 'xpan', zoom_out, 'reset', hover_tool, crosshair]
    p = figure(width=950,
               height=500,
               title="{} Data".format(dsn),
               x_axis_type="datetime",
               tools=tools,
               toolbar_location="above",
               x_range=(x_range_start, x_range_end),
               y_range=(0, max_hr + (24 * (len(names) + 1))),
               output_backend='webgl')

    # To have the Legend outside the plot, each line needs to be added to it
    legend_it = []

    for i in range(len(names)):
        legend_line = p.line(x=df.timestamp.iloc[-1:],
                             y=0,
                             color=colors[i],
                             alpha=1,
                             line_width=2)
        if names[i] in ["movement_raw", "base_state"]:
            legend_it.append((names[i], [
                legend_line,
                p.multi_line(xs='plot_xs',
                             ys='plot_' + names[i],
                             color=colors[i],
                             alpha=alphas[i],
                             source=source1)
            ]))
        else:
            bad_data_line = p.multi_line(xs='bad_x',
                                         ys='bad_' + names[i],
                                         color=colors[i],
                                         alpha=.1,
                                         source=source3)
            legend_it.append((names[i], [
                legend_line,
                p.multi_line(xs='good_x',
                             ys='good_' + names[i],
                             color=colors[i],
                             alpha=alphas[i],
                             source=source2), bad_data_line
            ]))

    legend_it.append(("Yellow notifications", [
        p.multi_line(xs='yellow',
                     ys='ys',
                     color='#F5BE41',
                     line_dash='dashed',
                     line_width=1.5,
                     source=source4)
    ]))
    legend_it.append(("Red notifications", [
        p.multi_line(xs='red',
                     ys='red_ys',
                     color='red',
                     line_dash='dashed',
                     source=source5)
    ]))
    # legend_it.append(("Red notifications", [p.circle(x='red', y='red_ys', color='red', size=6, source=source5)]))

    # Creating a location for the tooltip box to appear (so it doesn't cover the data)
    horizontal_line = p.line(x='date',
                             y='horizontal',
                             color='white',
                             alpha=0,
                             source=source)
    hover_tool.renderers.append(horizontal_line)

    p.xaxis.axis_label = 'Time'
    p.xaxis.formatter = DatetimeTickFormatter(days=["%m/%d %T"],
                                              months=["%m/%d %T"],
                                              hours=["%m/%d %T"],
                                              minutes=["%m/%d %T"],
                                              seconds=["%m/%d %T"],
                                              minsec=["%m/%d %T"],
                                              hourmin=["%m/%d %T"])

    legend = Legend(items=legend_it)
    legend.click_policy = "hide"  # Hide lines when they are clicked on
    p.add_layout(legend, 'right')
    return p, source, source1, source2, source3, source4, source5
예제 #8
0
 def test_adding_legend_doesnt_work_when_legends_already_added(
         self, p, source) -> None:
     p.add_layout(Legend())
     p.add_layout(Legend())
     with pytest.raises(RuntimeError):
         p.circle(x='x', y='y', legend='label', source=source)
예제 #9
0
def generate_spmfp_plot(circuit_years, circuit_races, circuit_results):
    """
    Plot mean of starting position - finish position and num DNFs vs time, with horizontal line showing average
    :param circuit_years: Circuit years
    :param circuit_races: Circuit races
    :param circuit_results: Circuit results
    :return: SPmFP plot layout
    """
    logging.info("Generating SPMFP plot")
    source = pd.DataFrame(columns=["year", "msp", "mfp", "mspmfp", "dnf"])
    for year in circuit_years:
        race = circuit_races[circuit_races["year"] == year]
        rid = race.index.values[0]
        results = circuit_results[circuit_results["raceId"] == rid]
        finishing_pos = pd.to_numeric(results["positionText"], errors="coerce")
        mspmfp = (results["grid"] - finishing_pos).mean()
        dnf = results.shape[0] - results["positionText"].str.isnumeric().sum()
        source = source.append({
            "year": year,
            "msp": round(results["grid"].mean(), 1),
            "mfp": finishing_pos.mean(),
            "mspmfp": mspmfp,
            "dnf": dnf
        }, ignore_index=True)

    min_year = source["year"].min()
    max_year = source["year"].max()
    min_y = min(source["dnf"].min(), source["mspmfp"].min(), 1.5)
    max_y = max(source["dnf"].max(), source["mspmfp"].max())
    if min_year == max_year:
        min_year -= 1
        max_year += 1
    spfp_plot = figure(
        title=u"Average Start Position minus Finish Position \u2014 How many places do drivers make up on average?",
        x_axis_label="Year",
        y_axis_label="Average start position minus finish position",
        x_range=Range1d(min_year, max_year, bounds=(min_year, max_year + 3)),
        y_range=Range1d(min(min_y - 2, -1), max_y + 2, bounds=(min(min_y - 2, -1), max_y)),
        tools="pan,xbox_zoom,xwheel_zoom,reset,box_zoom,wheel_zoom,save"
    )

    kwargs = {
        "x": "year",
        "source": source,
        "muted_alpha": 0.05
    }
    mspmfp_line = spfp_plot.line(y="mspmfp", line_width=2, color="white", **kwargs)
    dnf_line = spfp_plot.line(y="dnf", line_width=1.9, color="orange", line_alpha=0.8, **kwargs)

    # Mean lines
    kwargs = {
        "x": [1950, 2100],
        "line_alpha": 0.5,
        "line_width": 2,
        "line_dash": "dashed",
        "muted_alpha": 0.08
    }
    mspmfp_mean_line = spfp_plot.line(y=[source["mspmfp"].mean()] * 2, line_color="white", **kwargs)
    dnf_mean_line = spfp_plot.line(y=[source["dnf"].mean()] * 2, line_color="orange", **kwargs)

    # Zero line
    spfp_plot.add_layout(Span(line_color="white", location=0, dimension="width", line_alpha=0.3, line_width=1.5))

    # Legend
    legend_items = [
        LegendItem(label="Average Start - Finish Pos.", renderers=[mspmfp_line, mspmfp_mean_line]),
        LegendItem(label="Number of DNFs", renderers=[dnf_line, dnf_mean_line]),
    ]
    legend = Legend(items=legend_items, location="top_right", glyph_height=15, spacing=2, inactive_fill_color="gray")
    spfp_plot.add_layout(legend, "right")
    spfp_plot.legend.click_policy = "mute"
    spfp_plot.legend.label_text_font_size = "12pt"  # The default font size

    # Labels
    text_label_kwargs = dict(x=min_year + 0.5,
                             render_mode="canvas",
                             text_color="white",
                             text_font_size="12pt",
                             border_line_color="white",
                             border_line_alpha=0.7)
    label1 = Label(y=-0.9, text=" Finish lower than started ", **text_label_kwargs)
    label2 = Label(y=0.4, text=" Finish higher than start ", **text_label_kwargs)
    spfp_plot.add_layout(label1)
    spfp_plot.add_layout(label2)

    # Hover tooltip
    spfp_plot.add_tools(HoverTool(show_arrow=False, tooltips=[
        ("Year", "@year"),
        ("Mean Starting Position", "@msp"),
        ("Mean Finishing Position", "@mfp"),
        ("Mean Start minus Finish Position", "@mspmfp"),
        ("Number of DNFs", "@dnf"),
    ]))

    # Crosshair
    spfp_plot.add_tools(CrosshairTool(line_color="white", line_alpha=0.6))

    return spfp_plot
예제 #10
0
           x_axis_type="datetime",
           title="Geothermal Stocks")

l0 = p.line(listings[0].index,
            listings[0]["Close"],
            color="greenyellow",
            alpha=0.5)  # HTM
l1 = p.line(listings[1].index, listings[1]["Close"], color="red",
            alpha=0.5)  #ORA
# l2 = p.line(listings[2].index, listings[2]["Close"] ,color="deepskyblue", alpha=0.5) #CVX most expensive
l3 = p.line(listings[3].index, listings[3]["Close"], color="aqua",
            alpha=0.5)  #BRK-A
l4 = p.line(listings[4].index,
            listings[4]["Close"],
            color="deeppink",
            alpha=0.5)  #ENEL.MI
l5 = p.line(listings[5].index, listings[5]["Close"], color="gold",
            alpha=0.5)  #PIF.TO
l6 = p.line(listings[6].index, listings[6]["Close"], color="ivory",
            alpha=0.5)  #INE.TO
# l7 = p.line(listings[7].index, listings[7]["Close"] ,color="yellow", alpha=0.5) #LXV
# p.line(listings[8].index, listings[8]["Close"] ,color="aqua", alpha=0.5) #CLIME-B.ST

legend1 = Legend(items=[("HTM", [l0]), ("ORA", [l1]), ("BRK-A", [l3]),
                        ("ENEL.MI", [l4]), ("PIF.TO", [l5]), ("INE.TO", [l6])],
                 location=(70, 20),
                 orientation="horizontal")
p.add_layout(legend1, "below")
output_file("geostock.html")
show(p)
예제 #11
0
def line(
    df_in: pd.DataFrame,
    *args,
    plot_height: int = 500,
    plot_width: int = 1400,
    toolbar_location: str = 'below',
    legend_location: str = 'right',
    **kwargs,
) -> figure:
    """Lineplot in bokeh."""
    #df = df.reset_index()
    df = df_in.copy()
    if isinstance(df, pd.Series):
        df = pd.DataFrame(df)
        df.columns = ['data']
    if 'datetime' in df.columns:
        df = df.drop('datetime', axis=1)

    df.index.name = None

    for column in df.columns:
        if df[column].dtypes == 'object':
            for index, category in enumerate(
                    df[column].astype('category').cat.categories):
                print(index, category)
            df[column] = df[column].astype('category').cat.codes

    df_cds = ColumnDataSource(df)

    p = figure(
        x_axis_type='datetime',
        plot_height=plot_height,
        plot_width=plot_width,
        title='',
        x_axis_label='timestamp',
        y_axis_label='value',
        toolbar_location=toolbar_location,
        tools="reset,box_zoom",
        # buggy:
        # x_range=DataRange1d(
        #     # df.index[0],
        #     # df.index[-1],
        #     bounds=(df.index[0] - dt.timedelta(weeks=52),
        #             df.index[-1] + dt.timedelta(weeks=52)), ),
        x_range=DataRange1d(bounds='auto'),
    )

    col_num = 0
    colors = color(len(df.columns))
    legends = []
    tooltips = []
    for column in df.columns:
        r = p.line(
            x='index',
            y=column,
            name='value',
            color=colors[col_num],
            source=df_cds,
        )
        col_num += 1

        legends.append((column, [r]))

        tooltips.append((column, '@{%s}' % column))

    tooltips.append(('index', '@index{%F}'))

    p.add_tools(
        HoverTool(
            tooltips=tooltips,
            renderers=[r],
            mode='vline',
            point_policy='follow_mouse',
            line_policy='none',
            formatters={'index': 'datetime'},
        ))

    legend = Legend(items=legends, location=(0, 0))

    p.add_tools(CrosshairTool())

    wheel_zoom_tool = WheelZoomTool()
    wheel_zoom_tool.dimensions = 'width'
    p.add_tools(wheel_zoom_tool)
    p.toolbar.active_scroll = wheel_zoom_tool

    pan_tool = PanTool()
    pan_tool.dimensions = 'width'
    p.add_tools(pan_tool)

    p.add_layout(legend, legend_location)

    p.legend.click_policy = 'hide'

    show(p)

    return p
예제 #12
0
    def plot(self, source1, source2, source3, source4, source5, source6,
             source7, source8, source9):
        hover = HoverTool(tooltips=[
            ("x", "($x)"),
            ("y", "($y)"),
            ("NAME", "(@N)"),
        ])

        p = figure(title="TSNE/MACCS Keys FP",
                   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
예제 #13
0
from bokeh.plotting import figure, output_file, show
from bokeh.sampledata.stocks import AAPL, MSFT


def datetime(x):
    return np.array(x, dtype=np.datetime64)


p = figure(background_fill_color="#fafafa",
           x_axis_type="datetime",
           plot_width=800,
           plot_height=350)

r = p.multi_line(
    [datetime(AAPL['date']), datetime(MSFT['date'])],
    [AAPL['adj_close'], MSFT['adj_close']],
    color=["navy", "crimson"],
    line_width=2,
    alpha=0.6)

legend = Legend(items=[
    LegendItem(label="AAPL", renderers=[r], index=0),
    LegendItem(label="MSFT", renderers=[r], index=1),
],
                location="top_left")
p.add_layout(legend)

output_file("multi_legend.html")

show(p)
예제 #14
0
def scatterPlots(categories):
    TITLE = "Several blood chemicals versus Age quantile"
    figures = []  # list to contain all subplots
    posneg_list = []  # list to contain all dots in a plot
    colorPositive = "blue"  # color of positively tested
    colorNegative = "red"  # color of negatively tested

    count = 0
    for index in categories:  # create subplots for every bloodtype
        #  for the first one don't use x_range, the remaining all will use the same x_range
        if count != 0:  # a seperate plot is made for the first entry
            scatter = figure(title=index,
                             plot_width=400,
                             plot_height=300,
                             x_range=figures[0].x_range,
                             y_range=figures[0].y_range,
                             tools="save, pan, reset, wheel_zoom, box_select",
                             x_axis_label='age quantile',
                             y_axis_label='standardized test result')

        else:
            scatter = figure(  # plots for all the other blood values
                title=
                index,  # ... these are the same but they copy their axis from the first one
                plot_width=400,
                plot_height=300,
                y_range=(-4, 4),
                tools="save, pan, reset, wheel_zoom, box_select",
                x_axis_label='age quantile',
                y_axis_label='standardized test result')

        # create dot objects for the points in the plots
        p = scatter.square(x=jitter("Patient age quantile", 0.5),
                           y=index,
                           size=4,
                           color=colorPositive,
                           alpha=0.5,
                           source=sourcePos,
                           muted_alpha=0.1)
        n = scatter.circle(x=jitter("Patient age quantile", 0.5),
                           y=index,
                           size=4,
                           color=colorNegative,
                           alpha=0.5,
                           source=sourceNeg,
                           muted_alpha=0.1)

        posneg_list += [p]  # add dots to list
        posneg_list += [n]

        figures.append(scatter)  # add figure to the list of subfigures
        count += 1

    # Lines with the same color will share a same legend item
    legend_items = [
        LegendItem(label="Covid-19 positive",
                   renderers=[
                       thing for thing in posneg_list
                       if thing.glyph.line_color == colorPositive
                   ]),
        LegendItem(label="Covid-19 negative",
                   renderers=[
                       thing for thing in posneg_list
                       if thing.glyph.line_color == colorNegative
                   ])
    ]

    # use a dummy figure for the legend
    dum_fig = figure(plot_width=300,
                     plot_height=600,
                     outline_line_alpha=0,
                     toolbar_location=None)

    # set the components of the figure invisible
    for fig_component in [
            dum_fig.grid[0], dum_fig.ygrid[0], dum_fig.xaxis[0],
            dum_fig.yaxis[0]
    ]:
        fig_component.visible = False

    # The points referred by the legend need to be present in the figure ,so add them to figure renderers
    dum_fig.renderers += posneg_list

    # set the figure range outside of the range of all glyphs
    dum_fig.x_range.end = 1005
    dum_fig.x_range.start = 1000

    # add the legend
    dum_fig.add_layout(
        Legend(click_policy='mute',
               location='top_left',
               border_line_alpha=0,
               items=legend_items))

    # copy list to make it later possible to delete/ add items for the list without using original list (NOT YET USED)
    show_figures = figures

    splom = gridplot(show_figures, ncols=3, toolbar_location='right')
    plot = gridplot([[splom, dum_fig]], toolbar_location=None)
    return plot
예제 #15
0
plot.add_layout(line_f_glyph)

line_t = Line(x="x", y="ty", line_color="red", line_width=2)
line_t_glyph = plot.add_glyph(source, line_t)
plot.add_layout(line_t_glyph)

xaxis = LinearAxis()
plot.add_layout(xaxis, 'below')

yaxis = LinearAxis()
plot.add_layout(yaxis, 'left')

xgrid = Grid(dimension=0, ticker=xaxis.ticker)
ygrid = Grid(dimension=1, ticker=yaxis.ticker)

legend = Legend(orientation="bottom_left")
plot.add_layout(legend)


def on_slider_value_change(attr, old, new):
    global order
    order = int(new)
    update_data()


def on_text_value_change(attr, old, new):
    try:
        global expr
        expr = sy.sympify(new, dict(x=xs))
    except (sy.SympifyError, TypeError, ValueError) as exception:
        dialog.content = str(exception)
예제 #16
0
파일: taylor.py 프로젝트: bgyarfas/bokeh
plot.add_layout(line_f_glyph)

line_t = Line(x="x", y="ty", line_color="red", line_width=2)
line_t_glyph = plot.add_glyph(source, line_t)
plot.add_layout(line_t_glyph)

xaxis = LinearAxis()
plot.add_layout(xaxis, 'below')

yaxis = LinearAxis()
plot.add_layout(yaxis, 'left')

xgrid = Grid(dimension=0, ticker=xaxis.ticker)
ygrid = Grid(dimension=1, ticker=yaxis.ticker)

legend = Legend(location="top_right")
legend.items = [
    LegendItem(label=value("%s" % expr), renderers=[line_f_glyph]),
    LegendItem(label=value("taylor(%s)" % expr), renderers=[line_t_glyph]),
]
plot.add_layout(legend)

def on_slider_value_change(attr, old, new):
    global order
    order = int(new)
    update_data()

def on_text_value_change(attr, old, new):
    global expr

    try:
예제 #17
0
plot.add_layout(line_f_glyph)

line_t = Line(x="x", y="ty", line_color="red", line_width=2)
line_t_glyph = plot.add_glyph(source, line_t)
plot.add_layout(line_t_glyph)

xaxis = LinearAxis()
plot.add_layout(xaxis, 'below')

yaxis = LinearAxis()
plot.add_layout(yaxis, 'left')

xgrid = Grid(dimension=0, ticker=xaxis.ticker)
ygrid = Grid(dimension=1, ticker=yaxis.ticker)

legend = Legend(location="top_right")
plot.add_layout(legend)


def on_slider_value_change(attr, old, new):
    global order
    order = int(new)
    update_data()


def on_text_value_change(attr, old, new):
    try:
        global expr
        expr = sy.sympify(new, dict(x=xs))
    except (sy.SympifyError, TypeError, ValueError) as exception:
        dialog.content = str(exception)
예제 #18
0
def render_scatter(
    itmdt: Intermediate, plot_width: int, plot_height: int, palette: Sequence[str]
) -> Figure:
    """
    Render scatter plot with a regression line and possible most influencial points
    """

    # pylint: disable=too-many-locals

    df = itmdt["data"]
    xcol, ycol, *maybe_label = df.columns

    tooltips = [(xcol, f"@{{{xcol}}}"), (ycol, f"@{{{ycol}}}")]

    fig = Figure(
        plot_width=plot_width,
        plot_height=plot_height,
        toolbar_location=None,
        title=Title(text="Scatter Plot & Regression", align="center"),
        tools=[],
        x_axis_label=xcol,
        y_axis_label=ycol,
    )

    # Scatter
    scatter = fig.scatter(x=df.columns[0], y=df.columns[1], source=df)
    if maybe_label:
        assert len(maybe_label) == 1
        mapper = CategoricalColorMapper(factors=["=", "+", "-"], palette=palette)
        scatter.glyph.fill_color = {"field": maybe_label[0], "transform": mapper}
        scatter.glyph.line_color = {"field": maybe_label[0], "transform": mapper}

    # Regression line
    coeff_a, coeff_b = itmdt["coeffs"]
    line_x = np.asarray([df.iloc[:, 0].min(), df.iloc[:, 0].max()])
    line_y = coeff_a * line_x + coeff_b
    fig.line(x=line_x, y=line_y, line_width=3)

    # Not adding the tooltips before because we only want to apply tooltip to the scatter
    hover = HoverTool(tooltips=tooltips, renderers=[scatter])
    fig.add_tools(hover)

    # Add legends
    if maybe_label:
        nidx = df.index[df[maybe_label[0]] == "-"][0]
        pidx = df.index[df[maybe_label[0]] == "+"][0]

        legend = Legend(
            items=[
                LegendItem(
                    label="Most Influential (-)", renderers=[scatter], index=nidx
                ),
                LegendItem(
                    label="Most Influential (+)", renderers=[scatter], index=pidx
                ),
            ],
            margin=0,
            padding=0,
        )

        fig.add_layout(legend, place="right")
    return fig
예제 #19
0
fig.yaxis.formatter = FuncTickFormatter(code=log_axis_labels(max_tick=5))

# add the x-axis's label and use our custom log formatting
fig.xaxis.axis_label = 'Period (days)'
fig.xaxis.formatter = FuncTickFormatter(code=log_axis_labels(max_tick=5))

# add the second y-axis's label
fig.right[0].axis_label = 'Radius (Jupiter Radii)'

# set up all the legend objects
items = [
    LegendItem(label=ii + f' ({counts[missions.index(ii)]})', renderers=[jj])
    for ii, jj in zip(missions, glyphs)
]
# create the legend
legend = Legend(items=items, location="center")
legend.title = 'Discovered by'
legend.spacing = 10
fig.add_layout(legend, 'above')

# overall figure title
fig.title.text = 'Confirmed Transiting Planets'

# create the three lines of credit text in the two bottom corners
label_opts1 = dict(x=-68, y=42, x_units='screen', y_units='screen')

label_opts2 = dict(x=-68, y=47, x_units='screen', y_units='screen')

label_opts3 = dict(x=627,
                   y=64,
                   x_units='screen',
예제 #20
0
def create_graph(  # noqa: C901
    data: pd.DataFrame,
    unit: str = "Some unit",
    title: str = "A plot",
    x_label: str = "X",
    y_label: str = "Y",
    legend_location: Union[str, Tuple[float, float]] = "top_right",
    legend_labels: Tuple[str, Optional[str], Optional[str]] = (
        "Actual",
        "Forecast",
        "Schedules",
    ),
    x_range: Range1d = None,
    forecasts: pd.DataFrame = None,
    schedules: pd.DataFrame = None,
    show_y_floats: bool = False,
    non_negative_only: bool = False,
    tools: List[str] = None,
    sizing_mode="scale_width",
) -> Figure:
    """
    Create a Bokeh graph. As of now, assumes x data is datetimes and y data is numeric. The former is not set in stone.

    :param data: the actual data. Expects column name "event_value" and optional "belief_horizon" and "source" columns.
    :param unit: the (physical) unit of the data
    :param title: Title of the graph
    :param x_label: x axis label
    :param y_label: y axis label
    :param legend_location: location of the legend
    :param legend_labels: labels for the legend items
    :param x_range: values for x axis. If None, taken from series index.
    :param forecasts: forecasts of the data. Expects column names "event_value", "yhat_upper" and "yhat_lower".
    :param schedules: scheduled data. Expects column name "event_value".
    :param hover_tool: Bokeh hover tool, if required
    :param show_y_floats: if True, y axis will show floating numbers (defaults False, will be True if y values are < 2)
    :param non_negative_only: whether or not the data can only be non-negative
    :param tools: some tools for the plot, which defaults to ["box_zoom", "reset", "save"].
    :return: a Bokeh Figure
    """

    # Replace "source" column with "label" column (containing strings)
    data = replace_source_with_label(data)
    forecasts = replace_source_with_label(forecasts)
    schedules = replace_source_with_label(schedules)
    resolution = decide_plot_resolution(data)

    # Set x range
    if x_range is None:
        x_range = make_range(data.index)
    data = tz_index_naively(data)

    # Set default y range in case there is no data from which to derive a range
    y_range = None
    if (
        data["event_value"].isnull().all()
        and (forecasts is None or forecasts["event_value"].isnull().all())
        and (schedules is None or schedules["event_value"].isnull().all())
    ):
        y_range = Range1d(start=0, end=1)

    # Set default tools if none were given
    if tools is None:
        tools = ["box_zoom", "reset", "save"]
    if "belief_horizon" in data.columns and "label" in data.columns:
        hover_tool = create_hover_tool(unit, resolution, as_beliefs=True)
    else:
        hover_tool = create_hover_tool(unit, resolution, as_beliefs=False)
    tools = [hover_tool] + tools

    fig = figure(
        title=title,
        x_range=x_range,
        y_range=y_range,
        min_border=0,
        toolbar_location="right",
        tools=tools,
        h_symmetry=False,
        v_symmetry=False,
        sizing_mode=sizing_mode,
        outline_line_color="#666666",
    )

    if non_negative_only:
        fig.y_range.bounds = (0, None)
        fig.y_range.start = 0

    if data.empty:
        current_app.logger.warning("No data to show for %s" % title)

    # Format y floats
    if (
        not data.empty and show_y_floats is False and data["event_value"].size > 0
    ):  # apply a simple heuristic
        if forecasts is None or forecasts.empty:
            show_y_floats = max(data["event_value"].values) < 2
        else:
            show_y_floats = (
                max(max(data["event_value"].values), max(forecasts["event_value"])) < 2
            )

    palette, forecast_color, schedule_color = build_palette()
    legend_items: List[Tuple] = []

    # Plot power data. Support special case of multiple source labels.
    if not data.empty:
        data_groups = {legend_labels[0]: data}
        is_multiple = "label" in data.columns and len(data["label"].unique()) > 1
        if is_multiple:
            data_groups = {
                label: data.loc[data.label == label] for label in data["label"].unique()
            }
        legend_items = []
        for plot_label, plot_data in data_groups.items():
            ds = make_datasource_from(plot_data, resolution)
            if not is_multiple:
                ac = fig.circle(
                    x="x", y="y", source=ds, color=palette.pop(0), alpha=0.5, size=10
                )
            else:
                ac = fig.line(x="x", y="y", source=ds, color=palette.pop(0))
            legend_items.append((plot_label, [ac]))

    # Plot forecast data
    if forecasts is not None and not forecasts.empty:
        forecasts = tz_index_naively(forecasts)
        if "label" not in forecasts:
            forecasts["label"] = "Forecast from unknown source"
        labels = forecasts["label"].unique()
        for label in labels:
            # forecasts from different data sources
            label_forecasts = forecasts[forecasts["label"] == label]
            fds = make_datasource_from(label_forecasts, resolution)
            fc = fig.circle(x="x", y="y", source=fds, color=forecast_color, size=10)
            fl = fig.line(x="x", y="y", source=fds, color=forecast_color)

            # draw uncertainty range as a two-dimensional patch
            if "yhat_lower" and "yhat_upper" in label_forecasts:
                x_points = np.append(label_forecasts.index, label_forecasts.index[::-1])
                y_points = np.append(
                    label_forecasts.yhat_lower, label_forecasts.yhat_upper[::-1]
                )
                fig.patch(
                    x_points,
                    y_points,
                    color=forecast_color,
                    fill_alpha=0.2,
                    line_width=0.01,
                )
            if legend_labels[1] is None:
                raise TypeError("Legend label must be of type string, not None.")
            if label == labels[0]:
                # only add 1 legend item for forecasts
                legend_items.append((legend_labels[1], [fc, fl]))

    # Plot schedule data. Support special case of multiple source labels.
    if (
        schedules is not None
        and not schedules.empty
        and not schedules["event_value"].isnull().all()
    ):
        schedules = tz_index_naively(schedules)

        legend_label = "" if legend_labels[2] is None else legend_labels[2]
        schedule_groups = {legend_label: schedules}
        if "label" in schedules.columns and len(schedules["label"].unique()) > 1:
            schedule_groups = {
                label: schedules.loc[schedules.label == label]
                for label in schedules["label"].unique()
            }
        for plot_label, plot_data in schedule_groups.items():
            sds = make_datasource_from(plot_data, resolution)
            sl = fig.line(x="x", y="y", source=sds, color=palette.pop(0))

            if plot_label is None:
                raise TypeError("Legend label must be of type string, not None.")
            legend_items.append((plot_label, [sl]))

    fig.toolbar.logo = None
    fig.yaxis.axis_label = y_label
    fig.yaxis.formatter = NumeralTickFormatter(format="0,0")
    if show_y_floats:
        fig.yaxis.formatter = NumeralTickFormatter(format="0,0.00")
    fig.ygrid.grid_line_alpha = 0.5
    fig.xaxis.axis_label = x_label
    fig.xgrid.grid_line_alpha = 0.5

    if legend_location is not None:
        legend = Legend(items=legend_items, location=legend_location)
        fig.add_layout(legend, "center")

    return fig
예제 #21
0
def CreateMetricOneWord(w_i,
                        y_rep,
                        y_dem,
                        sizedot=9,
                        sizefont='28pt',
                        lgnd=False,
                        plotax=False,
                        plotsize=(350, 350),
                        Colors=('goldenrod', '#820872', 'black')):

    from sklearn.linear_model import LinearRegression
    from math import ceil
    import numpy as np

    from bokeh.models import ColumnDataSource, HoverTool, Label, Legend
    from bokeh.plotting import figure

    c1 = Colors[0]
    c2 = Colors[1]
    c3 = Colors[2]

    max_count = max(y_rep + y_dem)

    y_rep = [j / max_count for j in y_rep]
    y_dem = [j / max_count for j in y_dem]

    maxxy = 1.03  #+ 1
    minxy = -0.03

    x_vector = range(-10, 10)

    X_rep = np.array(y_rep).reshape(-1, 1)
    reg = LinearRegression(fit_intercept=False).fit(X=X_rep, y=y_dem)
    R2 = reg.score(X=X_rep, y=y_dem)
    slope = reg.coef_[0]
    neutrality_index = R2, np.exp(R2) * np.tanh(-(slope - 1))

    p_1 = figure(plot_width=plotsize[0],
                 plot_height=plotsize[1],
                 title='',
                 x_range=(minxy, maxxy),
                 y_range=(minxy, maxxy),
                 tools='')

    center_xy = (maxxy + minxy) / 2

    label_i = Label(x=center_xy,
                    y=center_xy,
                    text=w_i,
                    text_font_size=sizefont,
                    border_line_color=None,
                    border_line_alpha=1.0,
                    text_font_style='bold',
                    background_fill_color=None,
                    background_fill_alpha=1.0,
                    text_color='black',
                    text_baseline='middle',
                    text_align='center',
                    text_alpha=1,
                    level='underlay')

    p_1.add_layout(label_i)
    ref_line = p_1.line(y=x_vector,
                        x=x_vector,
                        color=c2,
                        alpha=1,
                        line_width=1.6,
                        line_dash='dashed')
    slope_line = p_1.line(x=x_vector,
                          y=[slope * x for x in x_vector],
                          color=c2,
                          alpha=1,
                          line_width=1.8,
                          line_dash='solid')

    r = p_1.scatter(x=y_rep,
                    y=y_dem,
                    color=c1,
                    alpha=1,
                    size=sizedot,
                    line_color=c3)

    if (lgnd):
        legend = Legend(items=[('Monthly mentions of "china" in (*)',
                                [r]), ('Reference line',
                                       [ref_line]), ('Slope line',
                                                     [slope_line])])
        legend.click_policy = "mute"
        legend.border_line_width = 0
        legend.label_text_font_size = '16pt'
        p_1.add_layout(legend, 'right')

    # Adjusting plot parameters
    #p.x_range.range_padding = 0.05
    p_1.xaxis.axis_label = "(*) r/republican"
    p_1.yaxis.axis_label = "(*) r/democrats"
    p_1.xaxis.visible = plotax
    p_1.yaxis.visible = plotax
    p_1.yaxis.axis_line_width = 1
    p_1.yaxis.ticker = []
    p_1.xaxis.axis_line_width = 1
    p_1.xaxis.ticker = []

    p_1.axis.axis_label_text_font_size = '16pt'
    p_1.axis.axis_label_text_font_style = 'normal'
    p_1.axis.axis_label_text_color = 'black'
    p_1.axis.axis_line_width = 1.5

    p_1.grid.visible = False
    p_1.background_fill_color = 'white'
    p_1.background_fill_alpha = 1

    p_1.outline_line_color = 'black'
    p_1.border_fill_color = None

    p_1.background_fill_color = "seashell"

    p_1.sizing_mode = 'scale_width'

    return (p_1, neutrality_index)
예제 #22
0
           height=350,
           title="US Population Age for each year",
           toolbar_location="right",
           tools="hover,tap, save",
           tooltips="$name: @$name")

v = p.vbar_stack(age, x='Year', width=0.9, color=colors, source=read_data)

p.y_range.start = 0
p.yaxis[0].axis_label = 'Population (%)'
p.x_range.range_padding = 0.1
p.xaxis.major_label_orientation = 1
p.xgrid.grid_line_color = None
p.axis.minor_tick_line_color = None
p.outline_line_color = None
# p.legend.location = "top_right"
# p.legend.orientation = "vertical"

legend = Legend(items=[
    ("Under 5", [v[0]]),
    ("5 to 19", [v[1]]),
    ("20 to 44", [v[2]]),
    ("45 to 64", [v[3]]),
    ("65+", [v[4]]),
],
                location=(0, 100))

p.add_layout(legend, 'right')

show(p)
예제 #23
0
        'y': [
            df_sleep['x'].min() * (slope) + intercept, df_sleep['x'].max() *
            (slope) + intercept
        ]
    })
plot_sleep_scatter.line(
    x='x',
    y='y',
    color='#154ba6',
    line_width=3,
    #line_dash="8 4",
    alpha=0.90,
    source=regline_cds,
    legend_label='reg')

legend = Legend()
plot_sleep_scatter.add_layout(legend, 'center')
plot_sleep_scatter.legend.orientation = 'vertical'
plot_sleep_scatter.legend.location = 'bottom_left'
plot_sleep_scatter.legend.click_policy = 'hide'

plot_sleep_scatter.legend.background_fill_alpha = 0.5
plot_sleep_scatter.legend.border_line_alpha = 0

movements = ['deadlift', 'barbell_bench_press', 'back_squat', 'shoulder_press']
three_lift_total = int(
    df_pr.query("reps==1")[['barbell_bench_press', 'back_squat',
                            'deadlift']].sum().sum())

plot_rep_prs, plot_rep_prs_cds = plot_ts(
    df_pr,
예제 #24
0
aDf = pd.DataFrame(data={'x': df.Day, 'y': df.Measurement})
a_source = ColumnDataSource(aDf)
bDf = pd.DataFrame(data={'x': df.Day, 'y': df.Projection})
b_source = ColumnDataSource(bDf)
model = Model(default_model)
result = model.fit(df.Measurement, x=df.Day, a=1, b=1)
fit = result.best_fit
cDf = pd.DataFrame(data={'x': df.Day, 'y': fit})
c_source = ColumnDataSource(cDf)

a = p.circle('x', 'y', size=8, source=a_source, color='grey', alpha=0.6)
b = p.line('x', 'y', source=b_source, line_width=3, color='blue', alpha=0.4)
c = p.line('x', 'y', source=c_source, line_width=3, color='red', alpha=0.4)

legend = Legend(items=[("Measurement", [a]), ("Projection",
                                              [b]), ("y = a + b*ln(x)", [c])])

source_data = {'a': [result.best_values['a']], 'b': [result.best_values['b']]}
source_data_table = ColumnDataSource(source_data)
columns = [
    TableColumn(field='a', title='a'),
    TableColumn(field='b', title='b')
]
data_table = DataTable(source=source_data_table,
                       columns=columns,
                       width=300,
                       height=50)

proj_resid = np.sum((df.Projection - df.Measurement)**2)
fit_resid = np.sum((df.Projection - fit)**2)
예제 #25
0
    def definePlot(self, source):

        # format the text of the plot
        p1 = figure(**self.plot_options, title='Covid Simulation',  toolbar_location='above')
        p1.yaxis.axis_label = 'Number of people'
        p1.xaxis.axis_label = 'Simulation time (days)'
        p1.xaxis[0].formatter = PrintfTickFormatter(format="%9.0f")
        p1.yaxis[0].formatter = PrintfTickFormatter(format="%9.0f")
        p1.xaxis.major_label_text_font_size = "10pt"
        p1.yaxis.major_label_text_font_size = "10pt"

        p2 = figure(**self.plot_options, title='Number of Susceptible people', toolbar_location='above')
        p2.yaxis.axis_label = 'Number of people'
        p2.xaxis.axis_label = 'Simulation time (days)'
        p2.xaxis[0].formatter = PrintfTickFormatter(format="%9.0f")
        p2.yaxis[0].formatter = PrintfTickFormatter(format="%9.0f")
        p2.xaxis.major_label_text_font_size = "10pt"
        p2.yaxis.major_label_text_font_size = "10pt"

        # format the plot line
        r0 = p2.line(source =source, x='x', y='sus', color='cyan', line_width=1,line_dash='dashed', legend='Susceptible')
        r1 = p2.circle(source=source, x='x', y='sus', color='cyan', size=10, legend='Susceptible')

        r2 = p1.line(source=source, x='x', y='exp',color='gold',line_width=1,line_dash='dotted', legend='Exposed')
        r3 = p1.circle(source=source, x='x', y='exp',color='gold',size=10, legend='Exposed')

        r4 = p1.line(source=source, x='x', y='inf',color='white',line_width=1,line_dash='dotted', legend='Infected')
        r5 = p1.circle(source=source, x='x', y='inf',color='white',size=10, legend='Infected')

        r6 = p1.line(source=source, x='x', y='sin',color='purple',line_width=1,line_dash='dotted', legend='Severe Infected')
        r7 = p1.circle(source=source, x='x', y='sin',color='purple',size=10, legend='Severe Infected')

        r8 = p1.line(source=source, x='x', y='qua',color='lime',line_width=1,line_dash='dotted', legend='Quarantined')
        r9 = p1.circle(source=source, x='x', y='qua',color='lime',size=10, legend='Quarantined')

        r10 = p1.line(source=source, x='x', y='imm',color='deepskyblue',line_width=1,line_dash='dotted', legend='Immunized')
        r11 = p1.circle(source=source, x='x', y='imm',color='deepskyblue',size=10, legend='Immunized')

        r12 = p1.line(source=source, x='x', y='dea',color='red',line_width=1,line_dash='dotted', legend='Dead')
        r13 = p1.circle(source=source, x='x', y='dea',color='red',size=10, legend='Dead')

        legend = Legend(items=[
                                ('Exposed', [r2, r3]),
                                ('Infected', [r4, r5]),
                                ('Severe Infected', [r6, r7]),
                                ('Quarantined', [r8, r9]),
                                ('Immunized', [r10, r11]),
                                ('Dead', [r12, r13])])

        # legends
        p1.legend.click_policy = 'hide'
        p1.background_fill_color = "black"
        p1.background_fill_alpha = 0.8
        p1.legend.location = "top_left"
        p1.legend.background_fill_color = "cyan"
        p1.legend.background_fill_alpha = 0.5
        p1.outline_line_width = 7
        p1.outline_line_alpha = 0.9
        p1.outline_line_color = "black"

        p2.legend.click_policy = 'hide'
        p2.background_fill_color = "black"
        p2.background_fill_alpha = 0.8
        p2.legend.location = "top_left"
        p2.legend.background_fill_color = "cyan"
        p2.legend.background_fill_alpha = 0.5
        p2.outline_line_width = 7
        p2.outline_line_alpha = 0.9
        p2.outline_line_color = "black"

        kz_map_tag = Div(text="""<div id="svg_holder" style="float:left;"> <svg width="780" height="530" id="statesvg"></svg> <div id="tooltip"></div>   </div>""", width=960, height=600)
        kz_map_row = row(kz_map_tag)
        pAll = row(p1, kz_map_row)

        return pAll
예제 #26
0
    recs.append(
        p.hbar(y='y',
               left='left',
               right='right',
               height='height',
               fill_alpha='fill_alpha',
               fill_color='fill_color',
               line_alpha=0.1,
               line_color='line_color',
               line_dash='solid',
               line_width=0.1,
               source=hbar_source))

# Create a legend
legend = Legend(items=[(stock, [l]) for stock, l in zip(unique_names, lines)],
                location=(0, 0),
                orientation='horizontal')

# Adjust the x view based upon the range of the data
time_range = xs[0].max() - xs[0].min()
p.x_range.start = np.min(xs[0]) - time_range * 0.1
p.x_range.end = np.max(xs[0])

# Add the stock logos to the plot
N = len(unique_names)
source = ColumnDataSource(
    dict(
        url=[image_urls.loc[name, 'image_url'] for name in unique_names],
        x1=[i.min() for i in xs],
        y1=max_ys,
        w1=[32] * N,
예제 #27
0
def display_timeline_values(
    data: pd.DataFrame,
    y: str,
    time_column: str = "TimeGenerated",
    source_columns: list = None,
    **kwargs,
) -> figure:
    """
    Display a timeline of events.

    Parameters
    ----------
    data : pd.DataFrame
        DataFrame as a single data set or grouped into individual
        plot series using the `group_by` parameter
    time_column : str, optional
        Name of the timestamp column
        (the default is 'TimeGenerated')
    y : str
        The column name holding the value to plot vertically
    source_columns : list, optional
        List of default source columns to use in tooltips
        (the default is None)

    Other Parameters
    ----------------
    x : str, optional
        alias of `time_column`
    title : str, optional
        Title to display (the default is None)
    ref_event : Any, optional
        Add a reference line/label using the alert time (the default is None)
    ref_time : datetime, optional
        Add a reference line/label using `ref_time` (the default is None)
    group_by : str
        (where `data` is a DataFrame)
        The column to group timelines on
    legend_column : str, optional
        (where `data` is a DataFrame)
        Name of the column used to generate the legend labels if a legend is
        to be displayed. Default is `group_by` parameter.
    yaxis : bool, optional
        Whether to show the yaxis and labels
    range_tool : bool, optional
        Show the the range slider tool (default is True)
    height : int, optional
        The height of the plot figure
        (the default is auto-calculated height)
    width : int, optional
        The width of the plot figure (the default is 900)
    color : str
        Default series color (default is "navy"). This is overridden by
        automatic color assignments if plotting a grouped chart
    kind : Union[str, List[str]]
        one or more glyph types to plot., optional
        Supported types are "circle", "line" and "vbar" (default is "vbar")

    Returns
    -------
    figure
        The bokeh plot figure.

    """
    reset_output()
    output_notebook()

    height: int = kwargs.pop("height", None)
    width: int = kwargs.pop("width", 900)
    title: str = kwargs.pop("title", None)
    time_column = kwargs.get("x", time_column)
    group_by: str = kwargs.get("group_by", None)
    show_yaxis: bool = kwargs.pop("yaxis", True)
    show_range: bool = kwargs.pop("range_tool", True)
    color: str = kwargs.get("color", "navy")
    legend_pos: str = kwargs.pop("legend", None)
    kind: Any = kwargs.pop("kind", ["vbar"])
    plot_kinds = kind if isinstance(kind, list) else [kind]

    ref_time, ref_label = _get_ref_event_time(**kwargs)

    graph_df, group_count_df, tool_tip_columns, series_count = _create_data_grouping(
        data, source_columns, time_column, group_by, color)

    # build the tool tips from columns (excluding these)
    tool_tip_items = [(f"{col}", f"@{col}") for col in tool_tip_columns]
    hover = HoverTool(tooltips=tool_tip_items,
                      formatters={"Tooltip": "printf"})

    # Create the Plot figure
    title = title if title else "Timeline"
    min_time = graph_df[time_column].min()
    max_time = graph_df[time_column].max()
    start_range = min_time - ((max_time - min_time) * 0.1)
    end_range = max_time + ((max_time - min_time) * 0.1)
    height = height if height else _calc_auto_plot_height(series_count)

    plot = figure(
        x_range=(start_range, end_range),
        min_border_left=50,
        plot_height=height,
        plot_width=width,
        x_axis_label="Event Time",
        x_axis_type="datetime",
        x_minor_ticks=10,
        y_axis_label=y,
        tools=[hover, "xwheel_zoom", "box_zoom", "reset", "save", "xpan"],
        toolbar_location="above",
        title=title,
    )
    plot.yaxis.visible = show_yaxis
    plot.ygrid.minor_grid_line_color = "navy"
    plot.ygrid.minor_grid_line_alpha = 0.1
    plot.ygrid.grid_line_color = "navy"
    plot.ygrid.grid_line_alpha = 0.3
    plot.xgrid.minor_grid_line_color = "navy"
    plot.xgrid.minor_grid_line_alpha = 0.1
    plot.xgrid.grid_line_color = "navy"
    plot.xgrid.grid_line_alpha = 0.3

    # set the tick datetime formatter
    plot.xaxis[0].formatter = _get_tick_formatter()

    # plot groups individually so that we can create an interactive legend
    if group_by:
        legend_items = []
        for _, group_id in group_count_df[group_by].items():
            first_group_item = graph_df[graph_df[group_by] == group_id].iloc[0]
            legend_label = str(first_group_item[group_by])
            inline_legend = str(group_id) if legend_pos == "inline" else None
            group_color = first_group_item["color"]
            row_source = ColumnDataSource(
                graph_df[graph_df[group_by] == group_id])
            p_series = []
            # create default plot args
            plot_args: Dict[str, Any] = dict(x=time_column,
                                             alpha=0.7,
                                             source=row_source,
                                             legend=inline_legend)
            if "vbar" in plot_kinds:
                p_series.append(
                    plot.vbar(top=y, width=4, color="color", **plot_args))
            if "circle" in plot_kinds:
                p_series.append(
                    plot.circle(y=y, size=4, color="color", **plot_args))
            if "line" in plot_kinds:
                p_series.append(
                    plot.line(y=y,
                              line_width=1,
                              line_color=group_color,
                              **plot_args))
            if not inline_legend:
                legend_items.append((legend_label, p_series))

        if legend_pos == "inline":
            # Position the inline legend
            plot.legend.location = "top_left"
            plot.legend.click_policy = "hide"
        elif legend_pos in ["left", "right"]:
            # Create the legend box outside of the plot area
            ext_legend = Legend(
                items=legend_items,
                location="center",
                click_policy="hide",
                label_text_font_size="8pt",
            )
            plot.add_layout(ext_legend, legend_pos)
    else:
        plot_args = dict(x=time_column,
                         color="color",
                         alpha=0.7,
                         source=ColumnDataSource(graph_df))
        if "vbar" in plot_kinds:
            plot.vbar(top=y, width=4, **plot_args)
        if "circle" in plot_kinds:
            plot.circle(y=y, size=4, **plot_args)
        if "line" in plot_kinds:
            plot.line(y=y, line_width=4, **plot_args)

    # if we have a reference, plot the time as a line
    if ref_time is not None:
        _add_ref_line(plot, ref_time, ref_label, series_count)

    if show_range:
        rng_select = _create_range_tool(
            data=graph_df,
            min_time=min_time,
            max_time=max_time,
            plot_range=plot.x_range,
            width=width,
            height=height,
            time_column=time_column,
        )
        show(column(plot, rng_select))
    else:
        show(plot)
    return plot
예제 #28
0
파일: taylor.py 프로젝트: zebulon2/bokeh
    return x, fy, ty


source = ColumnDataSource(data=dict(x=[], fy=[], ty=[]))

p = figure(x_range=(-7, 7), y_range=(-100, 200), width=800, height=400)
line_f = p.line(x="x", y="fy", line_color="navy", line_width=2, source=source)
line_t = p.line(x="x",
                y="ty",
                line_color="firebrick",
                line_width=2,
                source=source)

p.background_fill_color = "lightgrey"

legend = Legend(location="top_right")
legend.items = [
    LegendItem(label=value(f"{expr}"), renderers=[line_f]),
    LegendItem(label=value(f"taylor({expr})"), renderers=[line_t]),
]
p.add_layout(legend)


def update():
    try:
        expr = sy.sympify(text.value, dict(x=xs))
    except Exception as exception:
        errbox.text = str(exception)
    else:
        errbox.text = ""
    x, fy, ty = taylor(expr, xs, slider.value, (-2 * sy.pi, 2 * sy.pi), 200)
예제 #29
0
def mousover_plot(datadict, attr_x, attr_y, attr_color=None, attr_size=None, save_file=None, plot_title="",
                  point_transparency = 0.5, point_size=20, default_color="#2222aa", hidden_keys = []):
    """ Produces dynamic scatter plot that can be interacted with by mousing over each point to see its label
        Args:
            datadict (dict): keys contain attributes, values of lists of data from each attribute to plot (each list index corresponds to datapoint).
                             The values of all extra keys in this dict are considered (string) labels to assign to datapoints when they are moused over.
                             Apply _formatDict() to any entries in datadict which are themselves dicts.
            attr_x (str): name of column in dataframe whose values are shown on x-axis (eg. 'latency'). Can be categorical or numeric values
            attr_y (str): name of column in dataframe whose values are shown on y-axis (eg. 'validation performance'). Must be numeric values.
            attr_size (str): name of column in dataframe whose values determine size of dots (eg. 'memory consumption'). Must be numeric values.
            attr_color (str): name of column in dataframe whose values determine color of dots  (eg. one of the hyperparameters). Can be categorical or numeric values
            point_labels (list): list of strings describing the label for each dot (must be in same order as rows of dataframe)
            save_file (str): where to save plot to (html) file (if None, plot is not saved)
            plot_title (str): Title of plot and html file
            point_transparency (float): alpha value of points, lower = more transparent
            point_size (int): size of points, higher = larger
            hidden keys (list[str]): which keys of datadict NOT to show labels for.
    """
    try:
        with warning_filter():
            import bokeh
            from bokeh.plotting import output_file, ColumnDataSource, show, figure
            from bokeh.models import HoverTool, CategoricalColorMapper, LinearColorMapper, Legend, LegendItem, ColorBar
            from bokeh.palettes import Category20
        bokeh_imported = True
    except ImportError:
        bokeh_imported = False
    
    if not bokeh_imported:
        warnings.warn('AutoGluon summary plots cannot be created because bokeh is not installed. To see plots, please do: "pip install bokeh"')
        return None
    
    n = len(datadict[attr_x])
    for key in datadict.keys(): # Check lengths are all the same
        if len(datadict[key]) != n:
            raise ValueError("Key %s in datadict has different length than %s" % (key, attr_x))
    
    attr_x_is_string = any([type(val)==str for val in datadict[attr_x]])
    if attr_x_is_string:
        attr_x_levels = list(set(datadict[attr_x])) # use this to translate between int-indices and x-values
        og_x_vals = datadict[attr_x][:]
        attr_x2 = attr_x + "___" # this key must not already be in datadict.
        hidden_keys.append(attr_x2)
        datadict[attr_x2] = [attr_x_levels.index(category) for category in og_x_vals] # convert to ints
    
    legend = None
    if attr_color is not None:
        attr_color_is_string = any([type(val)==str for val in datadict[attr_color]])
        color_datavals = datadict[attr_color]
        if attr_color_is_string:
            attr_color_levels = list(set(color_datavals))
            colorpalette = Category20[20]
            color_mapper = CategoricalColorMapper(factors=attr_color_levels, palette=[colorpalette[2*i % len(colorpalette)] for i in range(len(attr_color_levels))])
            legend = attr_color
        else:
            color_mapper = LinearColorMapper(palette='Magma256', low=min(datadict[attr_color]), high=max(datadict[attr_color])*1.25)
        default_color = {'field': attr_color, 'transform': color_mapper}
    
    if attr_size is not None: # different size for each point, ensure mean-size == point_size
        attr_size2 = attr_size + "____"
        hidden_keys.append(attr_size2)
        og_sizevals = np.array(datadict[attr_size])
        sizevals = point_size + (og_sizevals - np.mean(og_sizevals))/np.std(og_sizevals) * (point_size/2)
        if np.min(sizevals) < 0:
            sizevals = -np.min(sizevals) + sizevals + 1.0
        datadict[attr_size2] = list(sizevals)
        point_size = attr_size2
    
    if save_file is not None:
        output_file(save_file, title=plot_title)
        print("Plot summary of models saved to file: %s" % save_file)
    
    source = ColumnDataSource(datadict)
    TOOLS="crosshair,pan,wheel_zoom,box_zoom,reset,hover,previewsave"
    p = figure(title=plot_title, tools=TOOLS)
    if attr_x_is_string:
        circ = p.circle(attr_x2, attr_y, line_color=default_color, line_alpha = point_transparency,
                fill_color = default_color, fill_alpha=point_transparency, size=point_size, source=source)
    else:
        circ = p.circle(attr_x, attr_y, line_color=default_color, line_alpha = point_transparency,
                fill_color = default_color, fill_alpha=point_transparency, size=point_size, source=source)
    hover = p.select(dict(type=HoverTool))
    hover.tooltips = OrderedDict([(key,'@'+key+'{safe}') for key in datadict.keys() if key not in hidden_keys])
    # Format axes:
    p.xaxis.axis_label = attr_x
    p.yaxis.axis_label = attr_y
    if attr_x_is_string: # add x-ticks:
        p.xaxis.ticker = list(range(len(attr_x_levels)))
        p.xaxis.major_label_overrides = {i: attr_x_levels[i] for i in range(len(attr_x_levels))}
    
    # Legend additions:
    if attr_color is not None and attr_color_is_string:
        legend_it = []
        for i in range(len(attr_color_levels)):
            legend_it.append(LegendItem(label=attr_color_levels[i], renderers = [circ], index=datadict[attr_color].index(attr_color_levels[i])))
        legend = Legend(items=legend_it, location=(0, 0))
        p.add_layout(legend, 'right')
    
    if attr_color is not None and not attr_color_is_string: 
        color_bar = ColorBar(color_mapper=color_mapper, title = attr_color, 
                             label_standoff=12, border_line_color=None, location=(0,0))
        p.add_layout(color_bar, 'right')
    
    if attr_size is not None:
        p.add_layout(Legend(items=[LegendItem(label='Size of points based on "'+attr_size + '"')]), 'below')
    
    show(p)
예제 #30
0
def ShowGraph(graphDict):

    if not graphDict['ShowGraph']:
        logger.warning('%s is not shown.', graphDict['GraphTitle'])
        return

    if (len(graphDict['Yaxes']) <= 0) or (len(graphDict['items']) <= 0):
        debug('No axes or no lines defined for graph "%s"',
              graphDict['GraphTitle'])
        return

    if graphDict['DBHost'] not in DBHostDict.keys():
        logger.warning('Unknown database host "%s" for plot "%s"' %
                       (graphDict['DBHost'], graphDict['GraphTitle']))
        return

    hostItem = DBHostDict[graphDict['DBHost']]

    # Signal that we want to reference local files for html output.
    res = Resources(mode='absolute')

    # output_file(graphDict["outputFile"], title=graphDict['GraphTitle'])

    plot = figure(title=graphDict['GraphTitle'],
                  tools="pan,wheel_zoom,box_zoom,reset,save,box_select",
                  x_axis_type='datetime',
                  plot_width=1600,
                  plot_height=800,
                  active_drag="box_zoom",
                  active_scroll="wheel_zoom")
    plot.title.align = "center"
    plot.title.text_font_size = "25px"
    plot.xaxis.axis_label = graphDict['XaxisTitle']
    # plot.xaxis.ticker = DatetimeTicker(num_minor_ticks = 4)
    plot.xaxis.formatter = DatetimeTickFormatter(seconds=["%M:%S"],
                                                 minutes=["%R"],
                                                 minsec=["%M:%S"],
                                                 hours=["%R"],
                                                 hourmin=["%m/%d %R"],
                                                 days=['%m/%d'])
    plot.toolbar.logo = None
    legend = Legend()
    # legend.items = [LegendItem(label="--- Left Axis ---"   , renderers=[])]
    legend.items = []

    #########   Setup Y axes
    ## Colors
    plot.yaxis.visible = False
    extra_y_ranges = {}

    for i in range(len(graphDict['Yaxes'])):
        ya = graphDict['Yaxes'][i]
        eyrName = 'Y%s_axis' % i
        clr = ya['color_map']
        if clr is None: clr = graphDict["graph_color_map"]
        ya["cmap"] = myPalette.Palette(clr,
                                       graphDict['max_palette_len'],
                                       loggingLevel=helperFunctionLoggingLevel)
        clr = ya['color']
        if clr is None: clr = "black"
        side = ya['location']
        extra_y_ranges[eyrName] = DataRange1d(range_padding=0.01)
        plot.extra_y_ranges = extra_y_ranges
        plot.add_layout(
            LinearAxis(y_range_name=eyrName,
                       axis_label=ya['title'],
                       axis_line_color=clr,
                       major_label_text_color=clr,
                       axis_label_text_color=clr,
                       major_tick_line_color=clr,
                       minor_tick_line_color=clr), side)

    for i in range(len(graphDict['items'])):
        item = graphDict['items'][i]
        info('--------------  %s  ------------' % item['dataname'])
        ya = graphDict['Yaxes'][item['axisNum']]
        colorGroup = ya['title']
        query = item['query'].format(
            my_schema=hostItem['myschema'],
            ha_schema=hostItem['haschema'],
            BeginDate=
            '{BeginDate}'  # Leave {BeginDate} unmolested; it is for later replacement.
        )
        if item['dataTimeZone'] == 'UTC':
            dataTimeOffsetUTC = 0
        else:
            dataTimeOffsetUTC = hostItem['ServerTimeFromUTC']
        data = GetData(item['datafile'], query, dataTimeOffsetUTC, hostItem)
        if data is None:
            logger.warning(
                'item "%s" of graph "%s" has no data and is skipped.' %
                (item['dataname'], graphDict['GraphTitle']))
            continue
        else:
            debug('Got %s rows of data.' % data.size)
        data = ColumnDataSource(data)
        debug('data column names are: %s; num rows is:  %s' %
              (data.column_names, data.to_df().size))
        yRangeName = 'Y%s_axis' % item['axisNum']
        for thisCol in data.column_names[1:]:
            debug('Column "%s" is plotted against y axis: "%s"' %
                  (thisCol, yRangeName))
            itemColor = item["color"]
            if item["color"] is None:
                itemColor = ya['cmap'].nextColor(colorGroup)
            else:
                debug('item color "%s" is defined in the item definition.' %
                      itemColor)
            r = eval('''plot.%s(x=data.column_names[0]
                , y = thisCol
                , source=data
                , color = itemColor, alpha=0.5
                , muted_color = itemColor, muted_alpha=1
                , name = thisCol
                , y_range_name=yRangeName)''' % item['lineType'])
            for (k, v) in item['lineMods'].items():
                s = 'r.%s = %s' % (k, v)
                debug('Executing line mod "%s"' % s)
                exec(s)
            extra_y_ranges[yRangeName].renderers.append(r)
            if item['includeInLegend']:
                legend.items.append(LegendItem(label=thisCol, renderers=[r]))
    plot.add_layout(legend)
    plot.legend.location = "top_left"
    plot.legend.click_policy = "mute"
    plot.add_tools(
        HoverTool(
            tooltips=[
                ('', '$name')  # use @{ } for field names with spaces
                ,
                ('', '$y{0.0}')  # use @{ } for field names with spaces
                ,
                ('', '@Time{%F %T}')
            ],
            formatters={
                '@Time': 'datetime'  # use 'datetime' formatter for 'x' field
                # use default 'numeral' formatter for other fields
            }))

    # show(plot)
    html = file_html(plot, res, graphDict['GraphTitle'])
    f = open(graphDict["outputFile"], mode='w')
    f.write(html)
    f.close()
    view(graphDict["outputFile"], new='tab')
import numpy as np
from bokeh.models import Legend
from bokeh.plotting import figure, show, output_file

x = np.linspace(0, 4 * np.pi, 100)
y = np.sin(x)

output_file("legend_labels.html")

p = figure(toolbar_location="above")

r0 = p.circle(x, y)
r1 = p.line(x, y)

r2 = p.line(x, 2 * y, line_dash=[4, 4], line_color="orange", line_width=2)

r3 = p.square(x, 3 * y, fill_color=None, line_color="green")
r4 = p.line(x, 3 * y, line_color="green")

legend = Legend(items=[
    ("sin(x)", [r0, r1]),
    ("2*sin(x)", [r2]),
    ("3*sin(x)", [r3, r4]),
],
                location="center")

p.add_layout(legend, 'right')

show(p)
예제 #32
0
def generate_dnf_plot(circuit_years, circuit_results, circuit_races, circuit_id):
    """
    Plots number of races, number of DNFs, and DNF percent for that year on the same plot. (2 different axes).
    :param circuit_years: Circuit years
    :param circuit_results: Circuit results
    :param circuit_races: Circuit races
    :param circuit_id: Circuit ID
    :return: Plot layout
    """
    # TODO refactor to use existing method
    logging.info("Generating dnf plot")
    if len(circuit_years) == 0:
        return Div()
    source = pd.DataFrame(columns=["n_races", "year", "n_drivers",
                                   "dnf_pct", "dnfs", "dnf_pct_str",
                                   "total_dnf_pct", "total_dnfs", "total_dnf_pct_str"])
    n_races = 0
    total_dnfs = 0
    total_drivers = 0
    for year in circuit_years:
        year_race = circuit_races[circuit_races["year"] == year]
        if year_race.shape[0] == 0:
            continue
        rid = year_race.index.values[0]
        year_results = circuit_results[circuit_results["raceId"] == rid]
        num_dnfs = year_results["position"].isna().sum()
        num_drivers = year_results.shape[0]
        total_dnfs += num_dnfs
        total_drivers += num_drivers
        if num_drivers > 0:
            dnf_pct = num_dnfs / num_drivers
            total_dnf_pct = total_dnfs / total_drivers
            n_races += 1
            source = source.append({
                "n_races": n_races,
                "n_drivers": num_drivers,
                "year": year,
                "dnf_pct": dnf_pct,
                "dnfs": num_dnfs,
                "dnf_pct_str": str(round(100 * dnf_pct, 1)) + "%",
                "total_dnf_pct": total_dnf_pct,
                "total_dnfs": total_dnfs,
                "total_dnf_pct_str": str(round(100 * total_dnf_pct, 1)) + "%",
            }, ignore_index=True)

    circuit_name = get_circuit_name(circuit_id)
    min_year = min(circuit_years)
    max_year = max(circuit_years)
    max_drivers = source["n_drivers"].max()
    if max_drivers == 0:
        return Div()
    dnf_plot = figure(
        title=u"Number of DNFs \u2014 " + circuit_name,
        y_axis_label="",
        x_axis_label="Year",
        x_range=Range1d(min_year, max_year, bounds=(min_year, max_year + 3)),
        tools="pan,xbox_zoom,xwheel_zoom,reset,box_zoom,wheel_zoom,save",
        y_range=Range1d(0, max_drivers, bounds=(-1000, 1000))
    )

    subtitle = 'Year DNFs refers to the number/percent of DNFs for that year, Total DNFs refers to all DNFs up to ' \
               'that point in time'
    dnf_plot.add_layout(Title(text=subtitle, text_font_style="italic"), "above")

    max_dnf_pct = max(source["dnf_pct"].max(), source["total_dnf_pct"].max())
    if max_dnf_pct > 0:
        k = max_drivers / max_dnf_pct
    else:
        k = 1
    source["dnf_pct_scaled"] = k * source["dnf_pct"]
    source["total_dnf_pct_scaled"] = k * source["total_dnf_pct"]

    # Other y axis
    y_range = Range1d(start=0, end=max_dnf_pct, bounds=(-0.02, 1000))
    dnf_plot.extra_y_ranges = {"percent_range": y_range}
    axis = LinearAxis(y_range_name="percent_range")
    axis.formatter = NumeralTickFormatter(format="0.0%")
    dnf_plot.add_layout(axis, "right")

    kwargs = {
        "x": "year",
        "line_width": 2,
        "line_alpha": 0.7,
        "source": source,
        "muted_alpha": 0.05
    }

    races_line = dnf_plot.line(y="n_races", color="white", **kwargs)
    drivers_line = dnf_plot.line(y="n_drivers", color="yellow", **kwargs)
    dnfs_line = dnf_plot.line(y="dnfs", color="aqua", **kwargs)
    dnf_pct_line = dnf_plot.line(y="dnf_pct_scaled", color="aqua", line_dash="dashed", **kwargs)
    total_dnfs_line = dnf_plot.line(y="total_dnfs", color="orange", **kwargs)
    total_dnf_pct_line = dnf_plot.line(y="total_dnf_pct_scaled", color="orange", line_dash="dashed", **kwargs)

    legend = [LegendItem(label="Number of Races", renderers=[races_line]),
              LegendItem(label="Number of Drivers", renderers=[drivers_line]),
              LegendItem(label="Year DNFs", renderers=[dnfs_line]),
              LegendItem(label="Year DNF Pct.", renderers=[dnf_pct_line]),
              LegendItem(label="Total DNFs", renderers=[total_dnfs_line]),
              LegendItem(label="Total DNF Pct.", renderers=[total_dnf_pct_line])]

    legend = Legend(items=legend, location="top_right", glyph_height=15, spacing=2, inactive_fill_color="gray")
    dnf_plot.add_layout(legend, "right")
    dnf_plot.legend.click_policy = "mute"
    dnf_plot.legend.label_text_font_size = "12pt"

    # Hover tooltip
    dnf_plot.add_tools(HoverTool(show_arrow=False, tooltips=[
        ("Number of Races", "@n_races"),
        ("Number of Drivers", "@n_drivers"),
        ("Year Num. DNFs", "@dnfs (@dnf_pct_str)"),
        ("Total Num. DNFs", "@total_dnfs (@total_dnf_pct_str)"),
        ("Year", "@year"),
    ]))

    # Crosshair tooltip
    dnf_plot.add_tools(CrosshairTool(line_color="white", line_alpha=0.6))

    return dnf_plot
예제 #33
0
def generate_times_plot(circuit_years, circuit_quali, circuit_fastest_lap_data, circuit_races, circuit_results,
                        circuit_id):
    """
    Plot quali, fastest lap, and average lap times vs year along with rating vs year
    :param circuit_years: Circuit years
    :param circuit_quali: Circuit quali
    :param circuit_fastest_lap_data: Circuit fastest lap data
    :param circuit_races: Circuit races
    :param circuit_results: Circuit results
    :param circuit_id: Circuit ID
    :return: Times plot layout
    """
    logging.info("Generating times plot")
    if circuit_quali.shape[0] == 0 and (circuit_fastest_lap_data.shape[0] == 0 or
                                        circuit_fastest_lap_data["avg_lap_time_millis"].isna().sum() ==
                                        circuit_fastest_lap_data["avg_lap_time_millis"].shape[0]):
        return Div(text="")
    source = pd.DataFrame(columns=["year",
                                   "quali_time", "quali_time_str",
                                   "fastest_lap_time", "fastest_lap_str",
                                   "avg_lap_time", "avg_lap_str",
                                   "rating"])

    for year in circuit_years:
        race = circuit_races[circuit_races["year"] == year]
        rid = race.index.values[0]

        # Qualifying
        year_quali = circuit_quali[circuit_quali["raceId"] == rid]
        quali_times = year_quali["q1"].append(year_quali["q2"].append(year_quali["q3"]))
        if quali_times.shape[0] == 0 or np.isnan(quali_times.idxmin()):
            quali_millis = np.nan
            quali_str = ""
        else:
            idxmin = int(quali_times.idxmin())
            quali_name = get_driver_name(year_quali.loc[idxmin, "driverId"])
            quali_millis = int(quali_times.loc[idxmin].min())
            quali_str = millis_to_str(quali_millis) + " by " + quali_name

        # Fastest and average lap
        year_fastest_lap_data = circuit_fastest_lap_data[circuit_fastest_lap_data["raceId"] == rid]
        if year_fastest_lap_data.shape[0] == 0:
            avg_lap_millis = np.nan
            avg_lap_str = ""
        else:
            avg_lap_millis = int(year_fastest_lap_data["avg_lap_time_millis"].mean())
            avg_lap_str = millis_to_str(avg_lap_millis)
        if year_fastest_lap_data.shape[0] == 0 or \
                year_fastest_lap_data["fastest_lap_time_millis"].isna().sum() == year_fastest_lap_data.shape[0]:
            fastest_lap_millis = np.nan
            fastest_lap_str = ""
        else:
            idxmin = int(year_fastest_lap_data["fastest_lap_time_millis"].idxmin())
            fastest_lap_name = get_driver_name(year_fastest_lap_data.loc[idxmin, "driver_id"])
            fastest_lap_millis = int(year_fastest_lap_data.loc[idxmin, "fastest_lap_time_millis"])
            fastest_lap_str = millis_to_str(fastest_lap_millis) + " by " + fastest_lap_name

        source = source.append({
            "year": year,
            "quali_time": quali_millis,
            "quali_time_str": quali_str,
            "fastest_lap_time": fastest_lap_millis,
            "fastest_lap_str": fastest_lap_str,
            "avg_lap_time": avg_lap_millis,
            "avg_lap_str": avg_lap_str,
            "rating": race["rating"].values[0],
        }, ignore_index=True)

    circuit_name = get_circuit_name(circuit_id)
    min_time = min(source["fastest_lap_time"].min(), source["avg_lap_time"].min(), source["quali_time"].min()) - 5000
    max_time = max(source["fastest_lap_time"].max(), source["avg_lap_time"].max(), source["quali_time"].max()) + 5000
    start = pd.to_datetime(min_time, unit="ms")
    end = pd.to_datetime(max_time, unit="ms")
    if pd.isna(start) or pd.isna(end):
        min_time = source["avg_lap_time"].min() - 5000
        max_time = source["avg_lap_time"].max() + 5000
        start = pd.to_datetime(min_time, unit="ms")
        end = pd.to_datetime(max_time, unit="ms")

    # Scale rating so that a 0=min_time, 10=max_time
    source["rating_scaled"] = (max_time - min_time) * (source["rating"] / 10) + min_time
    source["rating"] = source["rating"].fillna("")

    min_year = np.min(circuit_years)
    max_year = np.max(circuit_years)
    if min_year == max_year:
        min_year -= 0.01

    times_plot = figure(
        title=u"Qualifying, Fastest, Average, and Winning Times for " + circuit_name +
              " \u2014 Some data may be missing, zoom for more detail",
        x_axis_label="Year",
        y_axis_label="Lap Time",
        y_range=DataRange1d(start=start, end=end, bounds=(start, end)),
        x_range=Range1d(min_year, max_year, bounds=(min_year, max_year + 3)),
        tools="pan,xbox_zoom,xwheel_zoom,reset,box_zoom,wheel_zoom,save"
    )

    times_plot.yaxis.formatter = DatetimeTickFormatter(**DATETIME_TICK_KWARGS)
    column_source = ColumnDataSource(data=source)
    kwargs = {
        "x": "year",
        "source": column_source,
        "line_width": 2,
        "muted_alpha": 0.05
    }

    avg_lap_time_line = times_plot.line(y="avg_lap_time", line_color="white", **kwargs)
    legend_items = [
        LegendItem(label="Average Race Lap", renderers=[avg_lap_time_line]),
    ]
    tooltips = [
        ("Year", "@year"),
        ("Average Lap Time", "@avg_lap_str"),
    ]

    if source["quali_time"].isna().sum() < source.shape[0]:
        quali_time_line = times_plot.line(y="quali_time", line_color="red", **kwargs)
        legend_items.append(LegendItem(label="Qualifying Fastest", renderers=[quali_time_line]))
        tooltips.append(("Qualifying Lap Time", "@quali_time_str"))

    if source["fastest_lap_time"].isna().sum() < source.shape[0]:
        fastest_lap_time_line = times_plot.line(y="fastest_lap_time", line_color="yellow", **kwargs)
        legend_items.append(LegendItem(label="Fastest Race Lap", renderers=[fastest_lap_time_line]))
        tooltips.append(("Fastest Lap Time", "@fastest_lap_str"))

    # Add rating and other axis
    if source["rating"].replace("", np.nan).isna().sum() < source.shape[0]:
        rating_line = times_plot.line(y="rating_scaled", line_color="green", line_alpha=0.9, name="rating_line",
                                      **kwargs)
        legend_items.append(LegendItem(label="Average Rating", renderers=[rating_line]))
        tooltips.append(("Rating", "@rating"))
        y_range = Range1d(start=0, end=10, bounds=(0, 10))
        times_plot.extra_y_ranges = {"rating_range": y_range}
        axis = LinearAxis(y_range_name="rating_range", axis_label="Rating")
        times_plot.add_layout(axis, "right")

        def update_rating_axis():
            def dt_to_millis(t):
                if isinstance(t, float) or isinstance(t, int):
                    return t
                return t.microsecond / 1000 + t.second * 1000 + t.minute * 1000 * 60
            max_time = dt_to_millis(times_plot.y_range.end)
            min_time = dt_to_millis(times_plot.y_range.start)
            new_rating = (max_time - min_time) * (source["rating"].replace("", np.nan).astype(float) / 10) + min_time
            column_source.patch({
                "rating_scaled": [(slice(new_rating.shape[0]), new_rating)]
            })
            times_plot.extra_y_ranges.update({"rating_range": Range1d(start=0, end=10, bounds=(0, 10))})

        times_plot.y_range.on_change("start", lambda attr, old, new: update_rating_axis())
        times_plot.y_range.on_change("end", lambda attr, old, new: update_rating_axis())

    # Legend
    legend = Legend(items=legend_items, location="top_right", glyph_height=15, spacing=2, inactive_fill_color="gray")
    times_plot.add_layout(legend, "right")
    times_plot.legend.click_policy = "mute"
    times_plot.legend.label_text_font_size = "12pt"  # The default font size

    # Hover tooltip
    times_plot.add_tools(HoverTool(show_arrow=False, tooltips=tooltips))

    # Crosshair
    times_plot.add_tools(CrosshairTool(line_color="white", line_alpha=0.6))

    return times_plot
예제 #34
0
파일: scatter.py 프로젝트: bcipolli/PING
def plot_scatter_4D(data, x_key, y_key, size_key=None, color_key=None,
                    x_label=None, y_label=None, size_label=None, color_fn=None,
                    add_marker_text=False, ax=None, title=None,
                    plotengine='matplotlib'):
    """y_key can be a list..."""
    colors = np.asarray(['b','r','g','y'])

    if x_label is None:
        x_label = compute_scatter_label(x_key)
    if y_label is None:
        y_label = compute_scatter_label(y_key)
    if size_label is None:
        size_label = compute_scatter_label(size_key)

    # Data is in format needed to scatter, so we call it
    #   kwargs.
    kwargs = decimate_data(data, x_key=x_key, y_key=y_key,
                           size_key=size_key, color_key=color_key,
                           color_fn=color_fn)
    common_keys = kwargs.pop('keys')

    # Now plot it, and annotate it!
    if plotengine in ['matplotlib', 'mpld3']:
        if ax is None:
            ax = plt.figure(figsize=(11, 10.5)).gca()
        ax.scatter(**kwargs)
        ax.tick_params(labelsize=16)
        if x_label:
            ax.set_xlabel(x_label, fontsize=18)
        if y_label:
            ax.set_ylabel(y_label, fontsize=18)
        if size_label:
            if 'thickness' in size_label:  # hack
                loc = 'upper left'
            else:
                loc = 'upper right'
            ax.legend([size_label], loc=loc)

        if add_marker_text:
            # Interesting if it's outside of some range of values
            is_interesting = lambda v, varr, dist: np.abs(varr.mean() - v) >= dist * varr.std()

            for xi, (label, x, y) in enumerate(zip(common_keys, kwargs['x'], kwargs['y'])): # , kwargs['s']):
                locs = locals()
                annotations = [key for key, sval in zip(['x', 'y'], [1.35, 1.5])
                               if is_interesting(locs[key], kwargs[key], sval)]
                if len(annotations) > 0:
                    plt.annotate(
                        '%s (%s)' % (data.get_anatomical_name(data.get_nonhemi_key(label)), ', '.join(annotations)),
                        xy=(x, y), xytext=(25, 25),
                        textcoords='offset points', ha='right', va='bottom',
                        bbox=dict(boxstyle='round,pad=0.5', fc='yellow', alpha=0.5),
                        arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=0'),
                        fontsize=16)

        plt.axis('equal') #ax.set_aspect('equal')
        if np.any(kwargs['x'] <= 0) and np.any(kwargs['x'] >= 0):
            ax.plot([0, 0], ax.get_ylim(), 'k--')  # y-axis
        if np.any(kwargs['y'] <= 0) and np.any(kwargs['y'] >= 0):
           ax.plot(ax.get_xlim(), [0, 0], 'k--')  # x-axis
        plt.axis('tight')

        ax.get_figure().suptitle(title, fontsize=24)
    elif plotengine in ['bokeh', 'bokeh-silent']:
        from bokeh.io import show
        from bokeh.models.glyphs import Circle
        from bokeh.models import (Plot, DataRange1d, LinearAxis, Legend,
                                  ColumnDataSource, PanTool, WheelZoomTool,
                                  HoverTool, CrosshairTool, PreviewSaveTool,
                                  ResizeTool, BoxZoomTool, ResetTool)
        source = ColumnDataSource(data=dict(
            label=[data.get_anatomical_name(data.get_nonhemi_key(label))
                   for label in common_keys],
            x=kwargs['x'],
            y=kwargs['y'],
            s=kwargs.get('s', np.ones(kwargs['x'].shape) * 1000) / 1.E5))
        xdr = DataRange1d()
        ydr = DataRange1d()
        plot = Plot(x_range=xdr, y_range=ydr, name='scatter', title=title)
        circle = Circle(x="x", y="y", radius="s",
                        fill_color=kwargs.get('c', 'blue'),
                        line_color="black")
        circle_renderer = plot.add_glyph(source, circle)

        if size_label:
            legend = Legend(orientation="top_right")
            legend.legends = [(size_label, [circle_renderer])]
            plot.add_layout(legend)

        plot.add_layout(LinearAxis(axis_label=x_label), 'below')
        plot.add_layout(LinearAxis(axis_label=y_label), 'left')
        plot.add_tools(PanTool(), WheelZoomTool(), CrosshairTool(),
                       PreviewSaveTool(), ResizeTool(), BoxZoomTool(),
                       HoverTool(tooltips=[('label', '@label')]), ResetTool())
        ax = plot
    return ax