def _set_tools(self):
        wheel_zoom = WheelZoomTool()
        pan = PanTool()
        box_zoom = BoxZoomTool()
        box_select = BoxSelectTool()
        crosshair = CrosshairTool()
        tap = TapTool()
        save = SaveTool()
        reset = ResetTool()
        self.lasso_select = LassoSelectTool(
            renderers=self.circles,          # default = all available renderers
            select_every_mousemove=False,    # to enhance performance
        )

        self.lasso_select.overlay.line_alpha=0.9
        self.lasso_select.overlay.line_color="black"
        self.lasso_select.overlay.fill_alpha=0.2
        self.lasso_select.overlay.fill_color="grey"

        hover = self._get_hover_tool()
        self.tools = (
            pan, box_zoom, self.lasso_select, box_select,
            crosshair, save, reset, tap, wheel_zoom
        )
        self.plot.add_tools(*self.tools)
Exemple #2
0
    def _set_tools(self):
        wheel_zoom = WheelZoomTool()
        pan = PanTool()
        box_zoom = BoxZoomTool()
        box_select = BoxSelectTool()
        crosshair = CrosshairTool()
        tap = TapTool()
        save = SaveTool()

        lasso_select = LassoSelectTool(
            select_every_mousemove=False,  # enhance performance
        )

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

        tooltips = '''
            <style>
                .bk-tooltip>div:not(:nth-child(-n+5)) {{
                    display:none;
                }}

                .bk-tooltip>div {{
                    background-color: #dff0d8;
                    padding: 5px;
                }}
            </style>

            <b>STATION: </b> @{STNNBR} <br />
            <b>LON: </b> @X_WMTS{custom} <br />
            <b>LAT: </b> @Y_WMTS{custom} <br />
        '''

        hover = HoverTool(toggleable=True,
                          mode='mouse',
                          tooltips=tooltips,
                          renderers=[self.env.wmts_map_scatter],
                          formatters={
                              'X_WMTS': CustomJSHover(code=code % 0),
                              'Y_WMTS': CustomJSHover(code=code % 1),
                          })

        tools = (pan, box_zoom, lasso_select, hover, crosshair, tap,
                 wheel_zoom)
        self.env.wmts_map.add_tools(*tools)

        # set defaults
        self.env.wmts_map.toolbar.active_drag = pan
        self.env.wmts_map.toolbar.active_inspect = [crosshair, hover]
        self.env.wmts_map.toolbar.active_scroll = wheel_zoom
        self.env.wmts_map.toolbar.active_tap = None
Exemple #3
0
 def visualise(self, data):
     mapper = UMAPBase()
     mapper.embedding_ = data[["x", "y"]].values
     p = interactive(mapper,
                     labels=data["class"],
                     hover_data=data,
                     point_size=5,
                     interactive_text_search=False)
     del p.tools[len(p.tools) - 1]
     p.add_tools(get_hovertool())
     p.add_tools(LassoSelectTool())
     p_json = json_item(p)
     return p_json
Exemple #4
0
    def _set_tools(self):
        wheel_zoom = WheelZoomTool()
        pan = PanTool()
        box_zoom = BoxZoomTool()
        box_select = BoxSelectTool()
        crosshair = CrosshairTool()
        tap = TapTool()
        save = SaveTool()
        reset = ResetTool()     # TODO: add only to one plot, maybe with n_plot

        self.lasso_select = LassoSelectTool(
            renderers=self.circles,                  # default all available renderers
            select_every_mousemove=False,            # enhance performance
        )

        tooltips = '''
            <style>
                .bk-tooltip>div:not(:nth-child(-n+5)) {{
                    display:none;
                }}

                /* .bk-tooltip-custom + .bk-tooltip-custom {{
                    display: none;  sometimes everything is hidden with this
                }} */

                .bk-tooltip>div {{
                    background-color: #dff0d8;
                    padding: 5px;
                }}
            </style>

            <b>INDEX: </b> @INDEX <br>
            <b>{x}: </b> @{x} <br>
            <b>{x}_FLAG_W: </b> @{x}_FLAG_W <br>
            <b>{y}: </b> @{y} <br>
            <b>{y}_FLAG_W: </b> @{y}_FLAG_W <br>
        '''.format(x=self.x, y=self.y)

        hover = HoverTool(                  # TODO: try to make this toggleable
            renderers=self.circles,
            toggleable=True,
            mode='mouse',
            tooltips=tooltips,
        )

        tools = (
            pan, box_zoom, self.lasso_select, box_select,
            crosshair, save, reset, tap, wheel_zoom
        )
        self.plot.add_tools(*tools)
Exemple #5
0
        def update_plots(new):

            print("Starting update")

            nonlocal Estimators

            if not isinstance(Estimators, (type(np.array), list)):
                Estimators = np.array(Estimators)

            estimator_names = np.array(list(estimator_select.value))
            ix = np.isin(Estimator_Names, estimator_names)
            estimator_indices = [int(i) for i in np.where(ix)[0].flatten()]

            estimators = np.array(Estimators)[estimator_indices]

            variable1 = drop1.value
            variable2 = drop2.value
            y = drop3.value

            #Things to update:
            # image background i.e. image source √
            # observation source √
            #Color mapper values√
            #hover tool values √
            #Figure ranges √
            #Model score text things √

            #Lets calculate all the image and observation data first

            plots = [None for i in range(len(estimators))]
            image_sources = [None for i in range(len(estimators))]
            observation_sources = [None for i in range(len(estimators))]
            hover_tools = [None for i in range(len(estimators))]
            model_score_sources = [None for i in range(len(estimators))]
            glyphs0 = [None for i in range(len(estimators))]
            color_bars = [None for i in range(len(estimators))]
            p_circles = [None for i in range(len(estimators))]
            p_images = [None for i in range(len(estimators))]

            #Iterate over the estimators
            for idx, estimator in enumerate(estimators):
                #Find the title for each plot
                estimator_name = str(estimator()).split('(')[0]

                #Extract the needed data
                full_mat = X[[variable1, variable2, y]].dropna(how="any",
                                                               axis=0)

                #Define a class bijection for class colour mapping
                unique_classes, y_bijection = np.unique(full_mat[y],
                                                        return_inverse=True)
                full_mat['y_bijection'] = y_bijection

                #Rescale the X Data so that the data fits nicely on the axis/predictions are reliable
                full_mat[variable1 + "_s"] = StandardScaler().fit_transform(
                    full_mat[variable1].values.reshape((-1, 1)))
                full_mat[variable2 + "_s"] = StandardScaler().fit_transform(
                    full_mat[variable2].values.reshape((-1, 1)))

                #Define the Step size in the mesh
                delta = Delta

                #Separate the data into arrays so it is easy to work with
                X1 = full_mat[variable1 + "_s"].values
                X2 = full_mat[variable2 + "_s"].values
                Y = full_mat["y_bijection"].values

                #Define the mesh-grid co-ordiantes over which to colour in
                x1_min, x1_max = X1.min() - 0.5, X1.max() + 0.5
                x2_min, x2_max = X2.min() - 0.5, X2.max() + 0.5

                #Create the meshgrid itself
                x1, x2 = np.arange(x1_min, x1_max,
                                   delta), np.arange(x2_min, x2_max, delta)
                x1x1, x2x2 = np.meshgrid(x1, x2)

                #Create the train test split
                X_train, X_test, y_train, y_test = train_test_split(
                    full_mat[[variable1 + "_s", variable2 + "_s"]],
                    Y,
                    test_size=Test_Size,
                    random_state=Random_State)
                #Fit and predict/score the model
                model = estimator().fit(X=X_train, y=y_train)
                # train_preds = model.predict(X_train)
                # test_preds = model.predict(X_test)
                model_score = model.score(X_test, y_test)
                model_score_text = "Model score: %.2f" % model_score

                if hasattr(model, "decision_function"):
                    Z = model.decision_function(np.c_[x1x1.ravel(),
                                                      x2x2.ravel()])

                elif hasattr(model, "predict_proba"):
                    Z = model.predict_proba(np.c_[x1x1.ravel(), x2x2.ravel()])

                else:
                    print(
                        "This Estimator doesn't have a decision_function attribute and can't predict probabilities"
                    )

                Z = np.argmax(Z, axis=1)
                Z_uniques = np.unique(Z)

                unique_predictions = unique_classes[Z_uniques]

                Z = Z.reshape(x1x1.shape)

                #Add in the probabilities and predicitions for the tooltips
                full_mat["probability"] = np.amax(model.predict_proba(
                    full_mat[[variable1 + "_s", variable2 + "_s"]]),
                                                  axis=1)

                bijected_predictions = model.predict(
                    full_mat[[variable1 + "_s", variable2 + "_s"]])
                full_mat["prediction"] = unique_classes[bijected_predictions]

                #Add an associated color to the predictions
                number_of_colors = len(np.unique(y_bijection))

                #Create the hover tool to be updated
                hover = HoverTool(tooltips=[(
                    variable1, "@" +
                    variable1), (variable2, "@" +
                                 variable2), ("Probability", "@probability"),
                                            ("Prediction",
                                             "@prediction"), ("Actual",
                                                              "@" + y)])

                #Create the axes for all the plots
                plots[idx] = figure(x_axis_label=variable1,
                                    y_axis_label=variable2,
                                    title=estimator_name,
                                    x_range=(x1x1.min(), x1x1.max()),
                                    y_range=(x2x2.min(), x2x2.max()),
                                    plot_height=600,
                                    plot_width=600)

                #Create all the image sources
                image_data = dict()
                image_data['x'] = np.array([x1x1.min()])
                image_data["y"] = np.array([x2x2.min()])
                image_data['dw'] = np.array([x1x1.max() - x1x1.min()])
                image_data['dh'] = np.array([x2x2.max() - x2x2.min()])
                image_data['boundaries'] = [Z]

                image_sources[idx] = ColumnDataSource(image_data)

                #Create all the updatable images (boundaries)
                p_images[idx] = plots[idx].image(image='boundaries',
                                                 x='x',
                                                 y='y',
                                                 dw='dw',
                                                 dh='dh',
                                                 palette="RdBu11",
                                                 source=image_sources[idx])

                #Create the sources to update the observation points
                observation_sources[idx] = ColumnDataSource(data=full_mat)

                #Create all the updatable points
                low = full_mat["y_bijection"].min()
                high = full_mat["y_bijection"].max()
                cbar_mapper = LinearColorMapper(palette=RdBu[number_of_colors],
                                                high=high,
                                                low=low)

                p_circles[idx] = plots[idx].circle(
                    x=variable1 + "_s",
                    y=variable2 + "_s",
                    color=dict(field='y_bijection', transform=cbar_mapper),
                    source=observation_sources[idx],
                    line_color="black")

                #Create the hovertool for each plot
                hover_tools[idx] = hover

                #Add the hover tools to each plot
                plots[idx].add_tools(hover_tools[idx])

                #Create all the text sources (model scores) for the plots
                model_score_sources[idx] = ColumnDataSource(
                    data=dict(x=[x1x1.min() + 0.3],
                              y=[x2x2.min() + 0.3],
                              text=[model_score_text]))

                #Add the model scores to all the plots
                score_as_text = Text(x="x", y="y", text="text")
                glyphs0[idx] = plots[idx].add_glyph(model_score_sources[idx],
                                                    score_as_text)

                #Add a colorbar
                color_bars[idx] = ColorBar(
                    color_mapper=cbar_mapper,
                    ticker=BasicTicker(desired_num_ticks=number_of_colors),
                    label_standoff=12,
                    location=(0, 0),
                    bar_line_color="black")

                plots[idx].add_layout(color_bars[idx], "right")
                plots[idx].add_tools(LassoSelectTool(), WheelZoomTool())

                # configure so that no drag tools are active
                plots[idx].toolbar.tools = plots[idx].toolbar.tools[1:]
                plots[idx].toolbar.tools[0], plots[idx].toolbar.tools[
                    -2] = plots[idx].toolbar.tools[-2], plots[
                        idx].toolbar.tools[0]

            layout = gridplot([
                widgetbox(drop1, drop2, drop3, estimator_select, update_drop)
            ], [row(plot) for plot in plots])
            return layout

            #Finished the callback
            print("Ending Update")
            push_notebook(handle=handle0)
Exemple #6
0
from bokeh.models.tools import LassoSelectTool, BoxSelectTool, HoverTool  # for the additional way to add tools
import json

# df=pandas.read_csv("approx.csv")
df = pandas.read_csv("Sensor_record_20150810_002415_AndroSensor.csv", sep=';')
#df=pandas.read_csv("accound_details.csv",sep=',')

p = figure(
    plot_width=600,
    plot_height=400,
    tools='pan,wheel_zoom,reset,undo,redo',  # ,UndoTool,RedoTool', resize
    toolbar_location="right",  #"above","below","left","right"
    active_scroll="wheel_zoom",
    toolbar_sticky=False)

p.add_tools(LassoSelectTool())  # possible option to add tools
#//p.add_tools(BoxSelectTool(dimensions=["width"]))    # only in 1 dimension. note: To make a multiple selection, press the SHIFT key. To clear the selection, press the ESC key.
# p.add_tools(HoverTool())

print "lof_facctor: " + str(p.lod_factor)
print "lod_interval: " + str(p.lod_interval)
print "lod_threshold: " + str(p.lod_threshold)
print "lod_timeout: " + str(p.lod_timeout)

# Bokeh toolbars can have (at most) one active tool from each kind of gesture (drag, scroll, tap).
# configure so that no drag tools are active
# p.toolbar.active_drag = None
# configure so that Bokeh chooses what (if any) scroll tool is active
# p.toolbar.active_scroll = wheel_zoom # "auto"
# configure so that a specific PolySelect tap tool is active
# p.toolbar.active_tap = poly_select
Exemple #7
0
    def __init__(self, dataset, parameters):

        self.dataset = dataset

        # Set up the controls
        self.specials = Selector(
            name="Specials",
            kind="specials",
            css_classes=["specials"],
            entries={
                "Color-magnitude diagram": "cmd",
                "Period vs. radius": "pr",
                "Period vs. transit duration": "pdt",
            },
            default="Color-magnitude diagram",
        )
        self.data = Selector(
            name="Datasets",
            kind="datasets",
            css_classes=["data"],
            entries={"TOI Catalog": "toi", "Confirmed Planets": "confirmed"},
            default="Confirmed Planets",
        )
        self.xaxis = Selector(
            name="Build-Your-Own",
            kind="parameters",
            css_classes=["build-your-own"],
            entries=parameters,
            default="ra",
            title="X Axis",
        )
        self.yaxis = Selector(
            kind="parameters",
            css_classes=["build-your-own"],
            entries=parameters,
            default="dec",
            title="Y Axis",
        )
        self.size = Selector(
            name="Sides",
            kind="parameters",
            css_classes=["sides"],
            entries=parameters,
            default="dist",
            title="Marker Size",
            none_allowed=True,
        )
        self.color = Selector(
            kind="parameters",
            css_classes=["sides"],
            entries=parameters,
            default="dist",
            title="Marker Color",
            none_allowed=True,
        )

        # Set up the plot
        self.source = ColumnDataSource(
            data=dict(x=[], y=[], size=[], color=[])
        )
        self.plot = figure(
            plot_height=600,
            plot_width=700,
            title="",
            tooltips=[("TIC ID", "@ticid")],
            sizing_mode="scale_both",
        )
        self.plot.circle(
            x="x",
            y="y",
            source=self.source,
            size="size",
            color=linear_cmap(
                field_name="color", palette=Viridis256, low=0, high=1
            ),
            line_color=None,
        )
        self.plot.add_tools(
            BoxSelectTool(),
            BoxZoomTool(),
            LassoSelectTool(),
            PanTool(),
            PolySelectTool(),
            TapTool(),
            WheelZoomTool(),
            WheelPanTool(),
            ZoomInTool(),
            ZoomOutTool(),
            HoverTool(),
            CrosshairTool(),
            ResetTool(),
        )

        # Register the callback
        for control in [
            self.specials,
            self.data,
            self.xaxis,
            self.yaxis,
            self.size,
            self.color,
        ]:
            control.widget.on_change("value", self.callback)

        # Load and display the data
        self.callback(None, None, None)
Exemple #8
0
def create_bk_fig(x=None, xlab=None, x_min=None, x_max=None,
                  ylab=None, fh=None, fw=None,
                  title=None, pw=None, ph=None, x_axis_type="linear",
                  y_axis_type="linear", x_name=None, y_name=None, **kwargs):
    """ Generates a bokeh figure

    Parameters
    ----------
    x :obj:`DataArray`
        Contains x-axis data
    xlab : :obj:`str`
        X-axis label
    x_min : :obj:`float`
        Min x value
    x_max : :obj:`float`
        Max x value
    ylab : :obj:`str`
        Y-axis label
    fh: :obj:`int`
        True height of figure without legends, axes titles etc
    fw: :obj:`int`
        True width of figure without legends, axes etc
    title: :obj:`str`
        Title of plot
    pw: :obj:`int`
        Plot width including legends, axes etc
    ph: :obj:`int`
        Plot height including legends, axes etc
    x_axis_type: :obj:`str`
        Type of x-axis can be linear, log, or datetime
    y_axis_type: :obj:`str`
        Can be linear, log or datetime
    x_name: :obj:`str`
        Name of the column used for the x-axis. Mostly used to form tooltips
    y_name: :obj:`str`
        Name of the column used for the y-axis. Also used for tooltips
    add_grid: :obj:`bool`
        Whether or not to add grid
    add_title: :obj:`bool`
        Whether or not to add title to plot
    add_xaxis: :obj:`bool`
        Whether or not to add x-axis and tick marks
    add_yaxis: :obj:`bool`
        Add y-axis or not
    fix_plotsize: :obj:`bool`
        Enforce certain dimensions on plot. This is useful for ensuring a plot
        is not obscure by axes and other things. If activated, plot's
        dimensions will not be responsive. It utilises fw and fh.

    Returns
    -------
    p : :obj:`Plot`
        A bokeh Plot object

    """

    add_grid = kwargs.pop("add_grid", False)
    add_title = kwargs.pop("add_title", True)
    add_xaxis = kwargs.pop("add_xaxis", False)
    add_yaxis = kwargs.pop("add_yaxis", False)
    fix_plotsize = kwargs.pop("fix_plotsize", True)
    # addition plot specs
    pl_specs = kwargs.pop("pl_specs", {})
    # additional axis specs
    ax_specs = kwargs.pop("ax_specs", {})
    # ticker specs
    ti_specs = kwargs.pop("ti_specs", {})

    plot_specs = dict(background="white", border_fill_alpha=0.1,
                      border_fill_color="white", min_border=3,
                      name="plot", outline_line_dash="solid",
                      outline_line_width=2, outline_line_color="#017afe",
                      outline_line_alpha=0.4, output_backend="canvas",
                      sizing_mode="stretch_width", title_location="above",
                      toolbar_location="above")
    plot_specs.update(pl_specs)

    axis_specs = dict(minor_tick_line_alpha=0, axis_label_text_align="center",
                      axis_label_text_font="monospace",
                      axis_label_text_font_size="10px",
                      axis_label_text_font_style="normal",
                      major_label_orientation="horizontal")
    axis_specs.update(ax_specs)

    tick_specs = dict(desired_num_ticks=5)
    tick_specs.update(ti_specs)

    # Define frame width and height
    # This is the actual size of the plot without the titles et al
    if fix_plotsize and not(fh or fw):
        fw = int(0.98 * pw)
        fh = int(0.93 * ph)

    # define the axes ranges
    x_range = DataRange1d(name="p_x_range", only_visible=True)

    y_range = DataRange1d(name="p_y_range", only_visible=True)

    if x_min is not None and x_max is not None and x_name.lower() in ["channel", "frequency"]:
        x_range = Range1d(name="p_x_range", start=x_min, end=x_max)
        y_range.only_visible = False

    # define items to add on the plot
    p_htool = HoverTool(tooltips=[(x_name, "$x"),
                                  (y_name, "$y")],
                        name="p_htool", point_policy="snap_to_data")

    if x_name.lower() == "time":
        p_htool.tooltips[0] = (x_name, "$x{%d-%m-%Y %H:%M}")
        p_htool.formatters = {"$x": "datetime"}

    p_toolbar = Toolbar(name="p_toolbar",
                        tools=[p_htool, BoxSelectTool(), BoxZoomTool(),
                               # EditTool(), # BoxEditTool(), # RangeTool(),
                               LassoSelectTool(), PanTool(), ResetTool(),
                               SaveTool(), UndoTool(), WheelZoomTool()])
    p_ticker = BasicTicker(name="p_ticker", **tick_specs)

    # select the axis scales for x and y
    if x_axis_type == "linear":
        x_scale = LinearScale(name="p_x_scale")
        # define the axes and tickers
        p_x_axis = LinearAxis(axis_label=xlab, name="p_x_axis",
                              ticker=p_ticker, **axis_specs)
    elif x_axis_type == "datetime":
        x_scale = LinearScale(name="p_x_scale")
        # define the axes and tickers
        p_x_axis = DatetimeAxis(axis_label=xlab, name="p_x_axis",
                                ticker=p_ticker, **axis_specs)
    elif x_axis_type == "log":
        x_scale = LogScale(name="p_x_scale")
        p_x_axis = LogAxis(axis_label=xlab, name="p_x_axis",
                           ticker=p_ticker, **axis_specs)

    if y_axis_type == "linear":
        y_scale = LinearScale(name="p_y_scale")
        # define the axes and tickers
        p_y_axis = LinearAxis(axis_label=ylab, name="p_y_axis",
                              ticker=p_ticker, **axis_specs)
    elif x_axis_type == "datetime":
        y_scale = LinearScale(name="p_y_scale")
        # define the axes and tickers
        p_y_axis = DatetimeAxis(axis_label=xlab, name="p_y_axis",
                                ticker=p_ticker, **axis_specs)
    elif y_axis_type == "log":
        y_scale = LogScale(name="p_y_scale")
        # define the axes and tickers
        p_y_axis = LogAxis(axis_label=ylab, name="p_y_axis",
                           ticker=p_ticker, **axis_specs)

    # Create the plot object
    p = Plot(plot_width=pw, plot_height=ph, frame_height=fh, frame_width=fw,
             toolbar=p_toolbar, x_range=x_range, x_scale=x_scale,
             y_range=y_range, y_scale=y_scale, **plot_specs)

    if add_title:
        p_title = Title(align="center", name="p_title", text=title,
                        text_font_size="24px",
                        text_font="monospace", text_font_style="bold",)
        p.add_layout(p_title, "above")

    if add_xaxis:
        p.add_layout(p_x_axis, "below")

    if add_yaxis:
        p.add_layout(p_y_axis, "left")

    if add_grid:
        p_x_grid = Grid(dimension=0, ticker=p_ticker)
        p_y_grid = Grid(dimension=1, ticker=p_ticker)
        p.add_layout(p_x_grid)
        p.add_layout(p_y_grid)

    return p
Exemple #9
0
def create_daily_res_plot(res_forecast, load_forecast):
    """
    Graph the res injection forecast.

    Arguments:
        res_forecast (list): list of renewable energy injection forecast
        load_forecast (list): list of load forecast
    """
    # Datetime range
    time_of_day = []

    # Create x-axis
    # beginning of day
    today = datetime.datetime.today()
    beginning_of_day = datetime.datetime(year=today.year,
                                         month=today.month,
                                         day=today.day)

    for i in range(len(res_forecast)):
        time_of_day.append(beginning_of_day +
                           datetime.timedelta(minutes=i * 30))

    # Compute 75 percentile
    percentile = np.percentile(res_forecast, 75)

    # Initialize dictionaries
    normal_dict = {'x': [], 'y': [], 'percentage': []}
    peak_dict = {'x': [], 'y': [], 'percentage': []}

    for i in range(len(res_forecast)):
        if res_forecast[i] >= percentile:
            peak_dict['x'].append(time_of_day[i])
            peak_dict['y'].append(res_forecast[i])
            peak_dict['percentage'].append(
                percentage_of(res_forecast[i], load_forecast[i]))
        else:
            normal_dict['x'].append(time_of_day[i])
            normal_dict['y'].append(res_forecast[i])
            normal_dict['percentage'].append(
                percentage_of(res_forecast[i], load_forecast[i]))

    # Hover tool to properly display time of day and value on hover
    hover = HoverTool(
        tooltips=[("Time of day", "@x{%H:%M}"), ("Forecast Value", "@y MWh"),
                  ("Percentage of Daily Load", "@percentage{1.11} %")],
        formatters={'@x': 'datetime'},
    )

    # Create the figure
    plot = figure(
        x_axis_label="Time of Day",
        y_axis_label="Megawatts Per Hour",
        x_axis_type='datetime',
        sizing_mode="stretch_width",
        tools=[
            hover,
            BoxZoomTool(),
            ResetTool(),
            LassoSelectTool(),
            WheelZoomTool(),
            PanTool(),
            SaveTool()
        ],
    )

    plot.xaxis.formatter = DatetimeTickFormatter(
        minutes=["%H:%M"],
        hours=["%H:%M"],
    )

    # Set x-range and y-range
    plot.y_range = Range1d(min(res_forecast) - 200, max(res_forecast) + 100)
    plot.x_range = Range1d(time_of_day[0] - datetime.timedelta(minutes=5),
                           time_of_day[-1] + datetime.timedelta(minutes=5))

    # Set a grid
    plot.grid.minor_grid_line_color = '#eeeeee'

    # Set the font and style of labels
    plot.axis.axis_label_text_font = "raleway"
    plot.axis.axis_label_text_font_style = "normal"

    # Set the font of ticks on the axis
    plot.axis.major_label_text_font = "raleway"

    # Set the desired ticks
    plot.xaxis.ticker = DatetimeTicker(desired_num_ticks=24)
    plot.yaxis.ticker = AdaptiveTicker(desired_num_ticks=20)

    # Add a line plot
    plot.line(time_of_day,
              res_forecast,
              line_alpha=0.2,
              color="#264b01",
              line_width=1.5)

    # Add two circle plots one for the normal values and one for those that
    # are at or above the 75-percentile
    plot.circle('x', 'y', source=normal_dict, size=8, color="#264b01")
    plot.circle('x', 'y', source=peak_dict, size=15, color="#264b01")

    return components(plot)