Exemplo n.º 1
0
def verbose_formatter():
    '''
    Format bokeh time axis verbosely
    '''
    vf = DatetimeTickFormatter()
    vf.microseconds = ['%f us']
    vf.milliseconds = ['%S.%3N s']
    # vf.milliseconds = ['%H:%M:%S.%3N']
    vf.seconds = ['%H:%M:%S']
    vf.minsec = ['%H:%M:%S']
    vf.minutes = ['%m/%d %H:%M']
    vf.hourmin = ['%m/%d %H:%M']
    vf.hours = ['%m/%d %H:%M']
    vf.days = ['%m/%d', '%a%d']
    vf.months = ['%m/%Y', '%b %Y']
    vf.years = ['%Y']
    return vf
Exemplo n.º 2
0
def plot_time_series(activity: models.Activity):
    """
    Plotting function to create the time series plots shown in tha activity page. Depending
    on what data is available this creates the following plots:
    - Altitude
    - Heart Rate
    - Speed
    - Cadence
    - Temperature
    All plots share a connected vertical cross hair tools.

    Parameters
    ----------
    activity : models.Activity
        Activity model containing the required activity for which the plots should be generated

    Returns
    -------
    script, div : tuple(str, str)
        the html script and div elements used to render the plots in the html templates
    """

    attributes = activity.trace_file.__dict__
    lap_data = models.Lap.objects.filter(trace=activity.trace_file)
    plots = []
    lap_lines = []

    timestamps = pd.to_datetime(pd.Series(json.loads(
        attributes["timestamps_list"]),
                                          dtype=float),
                                unit="s")
    x_axis = pd.to_datetime(timestamps).dt.tz_localize("utc").dt.tz_convert(
        settings.TIME_ZONE)
    x_axis = x_axis - x_axis.min()

    for attribute, values in attributes.items():
        if attribute in attributes_to_create_time_series_plot_for:
            values = pd.Series(json.loads(values), dtype=float)
            if values.any():
                attribute = attribute.replace("_list", "")

                p = figure(
                    x_axis_type="datetime",
                    plot_height=int(settings.PLOT_HEIGHT / 2.5),
                    sizing_mode="stretch_width",
                    y_axis_label=plot_matrix[attribute]["axis"],
                )
                lap = _add_laps_to_plot(laps=lap_data, plot=p, y_values=values)
                lap_lines += lap
                if attribute == "altitude":
                    p.varea(
                        x=x_axis,
                        y1=values,
                        y2=values.min(),
                        color=plot_matrix[attribute]["second_color"],
                        fill_alpha=0.5,
                    )
                    p.line(
                        x_axis,
                        values,
                        line_width=2,
                        color=plot_matrix[attribute]["color"],
                        legend_label=plot_matrix[attribute]["title"],
                    )
                else:
                    p.line(
                        x_axis,
                        values,
                        line_width=2,
                        color=plot_matrix[attribute]["color"],
                        legend_label=plot_matrix[attribute]["title"],
                    )
                x_hover = ("Time", "@x")
                hover = HoverTool(
                    tooltips=[(plot_matrix[attribute]["title"],
                               f"@y {plot_matrix[attribute]['axis']}"),
                              x_hover],
                    mode="vline",
                )
                p.add_tools(hover)
                cross = CrosshairTool(dimensions="height")
                p.add_tools(cross)
                p.toolbar.logo = None
                p.toolbar_location = None
                p.xgrid.grid_line_color = None
                p.legend.location = "top_left"
                p.legend.label_text_font = "ubuntu"
                p.legend.background_fill_alpha = 0.7
                dtf = DatetimeTickFormatter()
                dtf.minutes = ["%M:%S"]
                p.xaxis.formatter = dtf
                p.xaxis.major_label_overrides = {0: "0:00"}
                plots.append(p)
                values.ffill(inplace=True)
                values.bfill(inplace=True)
                x_axis.ffill(inplace=True)
                x_axis.bfill(inplace=True)

    _link_all_plots_with_each_other(all_plots=plots, x_values=x_axis)

    all_plots = column(*plots)
    all_plots.sizing_mode = "stretch_width"

    if lap_data:
        # include button to toggle rendering of laps
        log.debug(f"found some Lap data for {activity}: {lap_data}")
        checkbox = CheckboxButtonGroup(labels=["Show Laps"],
                                       active=[0],
                                       width=100)

        js = """
            for (line in laps) {
                laps[line].visible = false;
                if (typeof markerGroup != "undefined") {
                    markerGroup.removeFrom(map);
                    }
            }
            for (i in cb_obj.active) {
                if (cb_obj.active[i] == 0) {
                    for (line in laps) {
                        laps[line].visible = true;
                        if (typeof markerGroup != "undefined") {
                            markerGroup.addTo(map);
                            }
                    }
                }
            }
        """
        callback = CustomJS(args=dict(laps=lap_lines, checkbox=checkbox),
                            code=js)
        checkbox.js_on_change("active", callback)
        layout = column(all_plots, checkbox)
        layout.sizing_mode = "stretch_width"
        script, div = components(layout)
    else:
        script, div = components(all_plots)

    return script, div