def make_basic_timeseries(source, object_name, variable, interval_label,
                          plot_width):
    """
    Make a basic timeseries plot (with either a step or line)
    and add a hover tool.

    Parameters
    ----------
    source : bokeh.models.ColumnDataSource
        The datasource with 'timestamp' and 'value' columns that will be
        plotted.
    object_name : str
        Name of the object to be plotted so an appropriate title can be made.
    variable : str
        Variable of the plotted object
    interval_label : str
        Interval label of the object to determine whether a line or step
        is most appropriate.
    plot_width : int
        The width of the output figure

    Returns
    -------
    bokeh.models.Figure
        The figure with the timeseries

    Raises
    ------
    KeyError
       If timestamp is not a column in source
    IndexError
       If the timestamp column is empty
    """
    timestamps = source.data['timestamp']
    first = pd.Timestamp(timestamps[0], tz='UTC')
    last = pd.Timestamp(timestamps[-1], tz='UTC')
    plot_method, plot_kwargs, hover_kwargs = plot_utils.line_or_step(
        interval_label)
    figure_title = build_figure_title(object_name, first, last)
    fig = figure(title=figure_title,
                 sizing_mode='scale_width',
                 plot_width=plot_width,
                 plot_height=300,
                 x_range=(first, last),
                 x_axis_type='datetime',
                 tools='pan,wheel_zoom,box_zoom,zoom_in,zoom_out,reset,save',
                 toolbar_location='above',
                 min_border_bottom=50)
    getattr(fig, plot_method)(x='timestamp',
                              y='value',
                              source=source,
                              **plot_kwargs)
    fig.yaxis.axis_label = plot_utils.format_variable_name(variable)
    fig.xaxis.axis_label = 'Time (UTC)'
    if variable == 'event':
        fig.yaxis.ticker = [0, 1]
        fig.yaxis.major_label_overrides = {1: 'True', 0: 'False'}
    add_hover_tool(fig, source, **hover_kwargs)
    return fig
Ejemplo n.º 2
0
def test_line_or_step(label, method):
    out = utils.line_or_step(label)
    assert out[0] == method
    assert isinstance(out[1], dict)
    assert isinstance(out[2], dict)
Ejemplo n.º 3
0
def timeseries(timeseries_value_cds,
               timeseries_meta_cds,
               start,
               end,
               units,
               timezone='UTC'):
    """
    Timeseries plot of one or more forecasts and observations.

    Parameters
    ----------
    timeseries_value_cds: bokeh.models.ColumnDataSource
        ColumnDataSource of timeseries data. See :py:func:`solarforecastarbiter.reports.reoports.figures.construct_timeseries_cds` for format.
    timeseries_meta_cds: bokeh.models.ColumnDataSource
        ColumnDataSource of metadata for each Observation Forecast pair. See :py:func:`solarforecastarbiter.reports.reoports.figures.construct_timeseries_cds` for format.
    start : pandas.Timestamp
        Report start time
    end : pandas.Timestamp
        Report end time
    timezone : str
        Timezone consistent with the data in the obs_fx_cds.

    Returns
    -------
    fig : bokeh.plotting.figure
    """  # NOQA
    palette = cycle(PALETTE)

    fig = figure(
        sizing_mode='scale_width',
        plot_width=900,
        plot_height=300,
        x_range=(start, end),
        x_axis_type='datetime',
        tools='pan,xwheel_zoom,box_zoom,box_select,lasso_select,reset,save',
        name='timeseries')

    plotted_objects = 0
    for obs_hash in np.unique(timeseries_meta_cds.data['observation_hash']):
        metadata = _extract_metadata_from_cds(timeseries_meta_cds, obs_hash,
                                              'observation_hash')
        pair_indices = _boolean_filter_indices_by_pair(timeseries_value_cds,
                                                       metadata['pair_index'])
        view = CDSView(source=timeseries_value_cds,
                       filters=[BooleanFilter(pair_indices)])
        plot_method, plot_kwargs, hover_kwargs = line_or_step(
            metadata['interval_label'])
        legend_label = metadata['observation_name']
        color = metadata['observation_color']
        getattr(fig, plot_method)(x='timestamp',
                                  y='observation_values',
                                  source=timeseries_value_cds,
                                  view=view,
                                  color=color,
                                  legend_label=legend_label,
                                  **plot_kwargs)
        plotted_objects += 1

    for fx_hash in np.unique(timeseries_meta_cds.data['forecast_hash']):
        metadata = _extract_metadata_from_cds(timeseries_meta_cds, fx_hash,
                                              'forecast_hash')
        pair_indices = _boolean_filter_indices_by_pair(timeseries_value_cds,
                                                       metadata['pair_index'])
        view = CDSView(source=timeseries_value_cds,
                       filters=[BooleanFilter(pair_indices)])
        plot_method, plot_kwargs, hover_kwargs = line_or_step(
            metadata['interval_label'])
        legend_label = metadata['forecast_name']
        color = next(palette)
        getattr(fig, plot_method)(x='timestamp',
                                  y='forecast_values',
                                  source=timeseries_value_cds,
                                  view=view,
                                  color=color,
                                  legend_label=legend_label,
                                  **plot_kwargs)
        plotted_objects += 1

    fig.legend.location = "top_left"
    fig.legend.click_policy = "hide"
    if plotted_objects > 10:
        fig.legend.label_height = 10
        fig.legend.label_text_font_size = '8px'
        fig.legend.glyph_height = 10
        fig.legend.spacing = 1
        fig.legend.margin = 0
    fig.xaxis.axis_label = f'Time ({timezone})'
    fig.yaxis.axis_label = f'Data ({units})'
    return fig