Beispiel #1
0
 def find_input_file(self, search_dirs):
     if self._input_file:
         utils.debug("searching for input_file={} defined for series".format(self._input_file))
         e = InputFileNotFoundError(self._input_file, search_dirs)
         self._input_file = find(self._input_file, search_dirs)
         if not self._input_file:
             raise e
Beispiel #2
0
 def find_input_files(self, search_dirs):
     if self._input_file:
         utils.debug("searching for input_file={} defined at top level of spec".format(self._input_file))
         e = InputFileNotFoundError(self._input_file, search_dirs)
         self._input_file = find(self._input_file, search_dirs)
         if not self._input_file:
             raise e
     for plot in self.subplots:
         plot.find_input_files(search_dirs)
Beispiel #3
0
def configure_xaxis(ax, axis_spec):
    if "lim" in axis_spec:
        ax.set_xlim(axis_spec["lim"])
    if "label" in axis_spec:
        ax.set_xlabel(axis_spec["label"])
    if "type" in axis_spec:
        value = axis_spec["type"]
        utils.debug("seting x axis type: {}".format(value))
        ax.set_xscale(value, basex=2)
Beispiel #4
0
def main(ctx, debug, include, quiet):
    # This is needed if main is called via setuptools entrypoint
    if ctx.obj is None:
        ctx.obj = {}

    utils.DEBUG = debug
    utils.QUIET = quiet
    ctx.obj["INCLUDE"] = include

    utils.debug("Running: {}".format(" ".join(sys.argv)))
Beispiel #5
0
def generate_plot(plot_spec):

    if "bar" == plot_spec.ty():
        utils.debug("Generating bar plot")
        return generate_bar(plot_spec)
    elif "errorbar" == plot_spec.ty():
        utils.debug("Generating errorbar plot")
        return generate_errorbar(plot_spec)
    else:
        utils.halt("Unrecognized plot type: {}".format(plot_spec.ty()))
Beispiel #6
0
def save(fig, path):
    utils.debug("saving bokeh figure: {}".format(path))
    if path.endswith(".png"):
        export_png(fig, filename=path)
    elif path.endswith(".svg"):
        export_svgs(fig, filename=path)
    elif path.endswith(".html"):
        bokeh.io.output_file(path)
        bokeh.io.save(fig)
    else:
        utils.error("unsupported bokeh output type {}".format(path))
Beispiel #7
0
def generator_regplot(ax, ax_spec):

    series_specs = ax_spec.series

    for i, series_spec in enumerate(series_specs):
        file_path = series_spec.input_file()
        label = series_spec.label_or(str(i))
        regex = series_spec.regex()
        yscale = series_spec.yscale()
        xscale = series_spec.xscale()
        x_field = series_spec.xfield()
        y_field = series_spec.yfield()
        utils.debug("series {}: opening {}".format(i, file_path))

        with GoogleBenchmark(file_path) as g:
            stats = g.keep_name_regex(regex).keep_stats()
            df = stats.stats_dataframe(x_field, y_field)
            df = df.sort_values(by=["x_mean"])
        x = df.loc[:, "x_mean"]
        y = df.loc[:, "y_mean"]
        e = df.loc[:, "y_stddev"]

        x *= xscale
        y *= yscale
        e *= yscale

        color = series_spec.color_or(styles.colors[i])

        # Draw scatter plot of values
        ax.errorbar(
            x, y, e, capsize=3, ecolor=color, linestyle='None', label=None)

        # compute a fit line and show
        z, _ = np.polyfit(x, y, 1, w=1. / e, cov=True)
        slope, intercept = z[0], z[1]
        ax.plot(
            x,
            x * slope + intercept,
            color=color,
            label=label + ": {:.2f}".format(slope) + " us/fault")

    if "title" in ax_spec:
        ax.set_title(ax_spec["title"])
    if "yaxis" in ax_spec:
        configure_yaxis(ax, ax_spec["yaxis"])
    if "xaxis" in ax_spec:
        configure_xaxis(ax, ax_spec["xaxis"])

    ax.legend(loc="best")
    ax.grid(True)

    return ax
Beispiel #8
0
def generate(figure_spec):

    fig = generate_subplots(figure_spec)

    # Set the figure size
    # fig.autofmt_xdate()
    if "size" in figure_spec:
        size = figure_spec["size"]
        utils.debug("Using figsize {}".format(size))
        fig.set_size_inches(size)
    fig.set_tight_layout(True)

    return fig
Beispiel #9
0
 def __init__(self, spec, spec_path=None):
     SpecificationBase.__init__(self, parent=None, spec=spec)
     input_file_mixin.__init__(self, None, spec)
     regex_mixin.__init__(self, None, spec)
     xfield_mixin.__init__(self, None, spec)
     yfield_mixin.__init__(self, None, spec)
     xscale_mixin.__init__(self, None, spec)
     yscale_mixin.__init__(self, None, spec)
     if "subplots" in spec:
         self.subplots = [
             PlotSpecification(self, s) for s in spec["subplots"]
         ]
     else:
         utils.debug("subplot not in spec")
         self.subplots = [PlotSpecification(self, spec)]
         self.subplots[0]["pos"] = (1, 1)
     self.size = spec.get("size", None)
     self.type_str = spec.get("type", None)
     self.output_spec = spec.get("output", None)
     self.spec_path = spec_path  # path of file this spec came from, if any
Beispiel #10
0
def generate(figure_spec):

    # figure out the size of the grid
    num_x = max([int(spec["pos"][0]) for spec in figure_spec.subplots])
    num_y = max([int(spec["pos"][1]) for spec in figure_spec.subplots])

    grid = [[None for i in range(num_x)] for j in range(num_y)]
    utils.debug("grid: {}".format(grid))

    for plot_spec in figure_spec.subplots:

        # propagate fields down to children if children don't override
        for k in ["yaxis", "xaxis"]:
            if k in figure_spec:
                utils.propagate_key_if_missing(figure_spec, k, plot_spec)

        pos = plot_spec["pos"]

        fig = generate_plot(plot_spec)
        grid[pos[1] - 1][pos[0] - 1] = fig

    grid = gridplot(grid, merge_tools=False)

    return grid
Beispiel #11
0
def spec(ctx, output, output_prefix, spec):
    """Create a figure from a spec file."""
    include = ctx.obj["INCLUDE"]

    # load YAML spec file
    figure_spec = Specification.load_yaml(spec)

    # apply include directories
    if include:
        utils.debug("searching dirs {}".format(include))
        figure_spec.find_input_files(include)

    # output path from command line or spec
    if output:
        utils.debug("output path from command line: {}".format(output))
        backend_str = backend.infer_from_path(output)
        utils.debug("inferred backend: {}".format(backend_str))
        output_specs = [(output, backend_str)]
    else:
        output_specs = figure_spec.output_specs()

    # prepend prefix to output_path
    if output_prefix:
        output_specs = [(os.path.join(output_prefix, path), backend_str)
                        for path, backend_str in output_specs]
        for (path, backend_str) in output_specs:
            utils.debug("prefixed output path: {}".format(path))

    # determine the figures that need to be constructed
    jobs = backend.construct_jobs(figure_spec, output_specs)

    utils.debug("{} jobs to run".format(len(jobs)))

    # run the jobs
    for job in jobs:
        backend.run(job)
Beispiel #12
0
def deps(ctx, output, spec, target):
    """Create a Makefile dependence"""

    utils.debug("Loading {}".format(spec))
    figure_spec = Specification.load_yaml(spec)
    include_dirs = ctx.obj["INCLUDE"]
    utils.debug("Searching for input_file values in: {}".format(include_dirs))
    try:
        figure_spec.find_input_files(include_dirs)
    except InputFileNotFoundError as e:
        utils.error(str(e))
        sys.exit(-1)

    utils.debug("Saving deps to {}".format(output))
    figure_spec.save_makefile_deps(output, target)
Beispiel #13
0
def generator_errorbar(ax, ax_cfg):
    series_specs = ax_cfg.series

    for i, series_spec in enumerate(series_specs):
        file_path = series_spec.input_file()
        label = series_spec.label_or(None)
        regex = series_spec.regex()
        yscale = series_spec.yscale()
        xscale = series_spec.xscale()
        x_field = series_spec.xfield()
        y_field = series_spec.yfield()
        linestyle = series_spec.linestyle()
        utils.debug("series {}: linestyle: {}".format(i, linestyle))
        utils.debug("series {}: opening {}".format(i, file_path))

        with GoogleBenchmark(file_path) as g:
            stats = g.keep_name_regex(regex).keep_stats()
            df = stats.stats_dataframe(x_field, y_field)
            df = df.sort_values(by=["x_mean"])
        x = df.loc[:, "x_mean"]
        y = df.loc[:, "y_mean"]
        e = df.loc[:, "y_stddev"]

        x *= xscale
        y *= yscale
        e *= yscale
        alpha = series_spec.alpha()
        color = series_spec.color_or(styles.colors[i])
        utils.debug("series {}: color = {} alpha = {}".format(i, color, alpha))
        ax.errorbar(x, y, e, capsize=3, label=label, color=color, linestyle=linestyle)

    if "title" in ax_cfg:
        ax.set_title(ax_cfg["title"])
    if "yaxis" in ax_cfg:
        configure_yaxis(ax, ax_cfg["yaxis"])
    if "xaxis" in ax_cfg:
        configure_xaxis(ax, ax_cfg["xaxis"])

    ax.legend(loc="best")
    ax.grid(True)

    return ax
Beispiel #14
0
def generator_bar(ax, ax_cfg):

    bar_width = ax_cfg.get("bar_width", 0.8)
    series_specs = ax_cfg.series
    utils.debug("Number of series: {}".format(len(series_specs)))

    df = pd.DataFrame()
    for i, series_spec in enumerate(series_specs):
        input_path = series_spec.input_file()
        label = series_spec.label_or(str(i))
        regex = series_spec.regex()
        y_field = series_spec.yfield()
        x_field = series_spec.xfield()
        y_scale = series_spec.yscale()
        x_scale = series_spec.xscale()
        input_path = series_spec.input_file()
        utils.require(input_path, "input_file should have been defined")
        utils.require(y_field, "yfield should have been defined")
        utils.require(x_field, "xfield should have been defined")

        utils.debug("series {}: Opening {}".format(i, input_path))
        utils.debug("series {}: filter regex is {}".format(i, regex))
        utils.debug("series {}: x field: {}".format(i, x_field))
        utils.debug("series {}: y field: {}".format(i, y_field))
        if x_scale != 1:
            utils.debug("series {}: xscale: {}".format(i, x_scale))
        if y_scale != 1:
            utils.debug("series {}: yscale: {}".format(i, y_scale))

        with GoogleBenchmark(input_path) as b:
            matches = b.keep_name_regex(regex)
            for entry in matches.benchmarks:
                utils.debug("name {} matched regex {}".format(entry["name"], regex))
            series_df = matches.xy_dataframe(x_field, y_field)

        if series_df.dtypes[x_field] == np.object:
            utils.debug("Not scaling non-numeric x data by {}".format(x_scale))
        else:
            series_df.loc[:, x_field] *= x_scale
        series_df.loc[:, y_field] *= y_scale
        series_df = series_df.rename(columns={y_field: label})
        series_df = series_df.set_index(x_field)

        # FIXME: this could be resolved with join?
        # https://stackoverflow.com/questions/27719407/pandas-concat-valueerror-shape-of-passed-values-is-blah-indices-imply-blah2
        if not series_df.index.is_unique:
            utils.warn(
                "multiple benchmark results with identical {} values. The plot might be weird.".format(
                    x_field))
        df = pd.concat([df, series_df], axis=1, sort=False)
    df = df.sort_index()

    df.plot.bar(ax=ax)

    if "xaxis" in ax_cfg:
        configure_yaxis(ax, ax_cfg["yaxis"])
    if "yaxis" in ax_cfg:
        configure_xaxis(ax, ax_cfg["xaxis"])

    if "title" in ax_cfg:
        ax.set_title(ax_cfg["title"])

    ax.legend(loc="best")

    return ax
Beispiel #15
0
def generate_errorbar(errorbar_spec):
    x_type = errorbar_spec.get("xaxis", {}).get("type", "auto")
    y_type = errorbar_spec.get("yaxis", {}).get("type", "auto")

    # Create the figure
    fig = figure(
        title=errorbar_spec["title"],
        x_axis_type=x_type,
        y_axis_type=y_type,
        plot_width=808,
        plot_height=int(500 / 2.0),
        toolbar_location='above',
        sizing_mode='scale_width')

    if "xaxis" in errorbar_spec:
        configure_xaxis(fig, errorbar_spec["xaxis"])
    if "yaxis" in errorbar_spec:
        configure_yaxis(fig, errorbar_spec["yaxis"])

    # Read all the series data
    df = pd.DataFrame()
    for i, series_spec in enumerate(errorbar_spec.series):

        label = series_spec.label_or(str(i))

        color = series_spec.color_or(styles.colors[i])
        utils.debug("series \"{}\": color {}".format(label, color))

        input_path = series_spec.input_file()
        regex = series_spec.regex()
        x_field = series_spec.xfield()
        y_field = series_spec.yfield()
        x_scale = series_spec.xscale()
        y_scale = series_spec.yscale()

        utils.debug("Opening {}".format(input_path))
        with GoogleBenchmark(input_path) as b:
            df = b.keep_name_regex(regex) \
                  .keep_stats() \
                  .stats_dataframe(x_field, y_field)

            if not df.size:
                utils.warn("Empty stats dataframe for path={} and x_field={} and y_field={}".format(input_path, x_field, y_field))

            df.loc[:, 'x_mean'] *= x_scale
            df.loc[:, 'x_median'] *= x_scale
            df.loc[:, 'x_stddev'] *= x_scale
            df.loc[:, 'y_mean'] *= y_scale
            df.loc[:, 'y_median'] *= y_scale
            df.loc[:, 'y_stddev'] *= y_scale

            df = df.sort_values(by=['x_mean'])

            fig.line(x=df.loc[:, "x_mean"], y=df.loc[:, "y_mean"], color=color, legend=label)

            df.loc[:, "lower"] = df.loc[:, 'y_mean'] - df.loc[:, 'y_stddev']
            df.loc[:, "upper"] = df.loc[:, 'y_mean'] + df.loc[:, 'y_stddev']
            error_source = ColumnDataSource(df)

            whisker = Whisker(
                source=error_source,
                base='x_mean',
                upper="upper",
                lower="lower",
                line_color=color)
            whisker.upper_head.line_color = color
            whisker.lower_head.line_color = color
            fig.add_layout(whisker)

    fig.legend.location = "top_left"
    fig.legend.click_policy = "hide"

    return fig
Beispiel #16
0
def save(fig, path):
    utils.debug("saving matplotlib figure: {}".format(path))
    fig.savefig(path, clip_on=False, transparent=False)
Beispiel #17
0
def generate_bar(bar_spec):

    x_axis_label = bar_spec.get("xaxis", {}).get("label", "")
    y_axis_label = bar_spec.get("yaxis", {}).get("label", "")
    x_axis_tick_rotation = bar_spec.get("xaxis", {}).get("tick_rotation", 90)

    # convert x axis tick rotation to radians
    x_axis_tick_rotation = x_axis_tick_rotation / 360.0 * 2 * math.pi

    x_type = bar_spec.get("xaxis", {}).get("type", "auto")
    y_type = bar_spec.get("yaxis", {}).get("type", "auto")

    # Read all the series data
    df = pd.DataFrame()
    for i, series_spec in enumerate(bar_spec.series):

        input_path = series_spec.input_file()
        y_scale = series_spec.yscale()
        x_scale = series_spec.xscale()
        regex = series_spec.regex()
        utils.debug("Using regex {}".format(regex))
        x_field = series_spec.xfield()
        y_field = series_spec.yfield()
        label = series_spec.label_or(str(i))

        utils.debug("Opening {}".format(input_path))
        with GoogleBenchmark(input_path) as b:
            new_df = b.keep_name_regex(regex).xy_dataframe(x_field, y_field)
            new_df.loc[:, x_field] *= x_scale
            new_df.loc[:, y_field] *= y_scale
            new_df = new_df.rename(columns={y_field: label})

            new_df = new_df.set_index(x_field)
            df = pd.concat([df, new_df], axis=1, sort=False)

    # convert index to a string
    df.index = df.index.map(str)
    source = ColumnDataSource(data=df)

    source.data[x_field] = map(str, source.data[x_field])
    # Figure out the unique x values that we'll need to plot
    x_range = list(df.index)
    utils.debug("x_range contains {} unique values".format(len(x_range)))

    # Create the figure
    fig = figure(
        title=bar_spec["title"],
        x_axis_label=x_axis_label,
        y_axis_label=y_axis_label,
        x_axis_type=x_type,
        y_axis_type=y_type,
        x_range=x_range,
        plot_width=800,
        plot_height=int(300),
        toolbar_location='above',
    )

    # offset each series
    group_width = 1.0 / (
        len(bar_spec.series) + 1
    )  # each group of bars is 1 wide, leave 1 bar-width between groups
    bar_width = group_width * 0.95  # small gap between bars

    # plot the bars
    for i, series_spec in enumerate(bar_spec.series):

        color = series_spec.color_or(styles.colors[i])

        dodge_amount = -0.5 + (i + 1) * group_width
        utils.debug("{}".format(dodge_amount))
        fig.vbar(
            x=dodge(x_field, dodge_amount, range=fig.x_range),
            top=series_spec["label"],
            width=bar_width,
            source=source,
            color=color)

    fig.xaxis.major_label_orientation = x_axis_tick_rotation

    return fig