API — ppbcc.plot#

Module Overview#

Plotting functions for benchmark and performance-portability data.

The rendered results of these functions are shown in Available Plots.

Cascade and Combined Plots#

Cascade and combined performance-portability plots.

ppbcc.plot.cascade.plot_cascade(efficiency, portability, problem_title, remove_description=False, navchart_data=None, complexity_metric=None, scaling_data=None, log_complexity=False, selected_size=None, average_over='pp', show_legends=True)[source]#

Create a Cascade Plot following the P3 Analysis Library layout.

Parameters:
  • efficiency (DataFrame) – Application efficiency by problem, application, and hardware.

  • portability (DataFrame) – Performance portability by problem and application.

  • problem_title (str) – Problem name or names used in the title.

  • remove_description (bool) – Whether to hide bracketed legend descriptions.

  • navchart_data (DataFrame | None) – Optional complexity/PP data for combined mode.

  • complexity_metric (str | None) – Complexity column used in combined mode.

  • scaling_data (DataFrame | None) – Optional per-size PP data for combined mode.

  • log_complexity (bool) – Whether the complexity axis is logarithmic.

  • selected_size (float | str | None) – Optional benchmark size or size-summary mode for the two upper panels.

  • average_over (str) – For an averaged size, whether PP was averaged over the sizes (pp) or computed from the averaged efficiencies (efficiency); only changes the note above the panels.

  • show_legends (bool) – Whether legends are embedded in the plot.

Returns:

The Matplotlib figure.

Raises:

ValueError – If combined-mode inputs are incomplete.

Return type:

Figure

Navchart#

Navchart plotting for complexity and performance portability.

ppbcc.plot.navchart.plot_navchart(data, metric, problem_title, remove_description=False, log_complexity=False, show_legends=True)[source]#

Create a Navchart of complexity and performance portability.

Parameters:
  • data (DataFrame) – Matched problem, application, PP, and complexity data.

  • metric (str) – Complexity metric column and x-axis label.

  • problem_title (str) – Problem name or names used in the title.

  • remove_description (bool) – Whether to hide bracketed legend descriptions.

  • log_complexity (bool) – Whether the complexity axis is logarithmic.

  • show_legends (bool) – Whether legends are embedded in the plot.

Returns:

The Matplotlib figure.

Return type:

Figure

Complexity Comparison#

Scatter plot comparing two code-complexity metrics against each other.

ppbcc.plot.complexity_comparison.ABOVE_LINE_COLOR = '#d62728'#

above the identity line the y metric charges a paradigm more than the x metric does, below it the x metric charges more.

Type:

Region shading

ppbcc.plot.complexity_comparison.ABOVE_LINE_TEXT = 'Dense\nLines'#

What each half-plane means, in the reader’s terms rather than the metrics’.

ppbcc.plot.complexity_comparison.AXIS_LABEL_FONT_SCALE = 1.15#

The chart is printed small beside a shared legend, so the axis labels, the region captions and the markers are all set above the inherited defaults.

ppbcc.plot.complexity_comparison.BASELINE_BOX_POSITION = (0.975, 0.5)#

Where the baseline key sits, in axes coordinates. Its top edge starts at half height so the box grows downwards into the empty lower-right corner, clearing both the markers and the “Verbose Code” caption below it.

ppbcc.plot.complexity_comparison.LABEL_OFFSETS = ((12, 0, 'left'), (-12, 0, 'right'), (12, 13, 'left'), (-12, 13, 'right'), (12, -13, 'left'), (-12, -13, 'right'), (0, 17, 'center'), (0, -17, 'center'), (12, 26, 'left'), (-12, -26, 'right'))#

Candidate label offsets in points, tried in order until one is free.

ppbcc.plot.complexity_comparison.plot_complexity_comparison(data, x_metric, y_metric, problem_title, remove_description=False, log_axes=True, show_legends=True, baselines=None)[source]#

Plot two complexity metrics against each other with an identity line.

Both metrics are relative to the sequential C++ baseline, so they share one dimensionless scale and the identity line is meaningful: a paradigm above it is charged more by y_metric than by x_metric, and one below it is charged more by x_metric. The two half-planes are captioned with what they mean for the source rather than for the metrics.

Parameters:
  • data (DataFrame) – Application labels with both relative metric columns.

  • x_metric (str) – Column plotted on the x axis.

  • y_metric (str) – Column plotted on the y axis.

  • problem_title (str) – Problem name or names used in the title.

  • remove_description (bool) – Whether to hide bracketed descriptions.

  • log_axes (bool) – Whether both axes are logarithmic.

  • show_legends (bool) – Whether the legend and the per-point labels are drawn. With an external legend the paradigm colors are keyed there, so the labels are dropped: they do not survive the reduction to a narrow column anyway.

  • baselines (tuple[float, float] | None) – Absolute sequential C++ values of x_metric and y_metric. Both axes are percentages of these, so the key states what 100 % stands for. Omitted when the values are unknown or when several problems with different baselines share one chart.

Returns:

The Matplotlib figure.

Raises:

ValueError – If fewer than two paradigms can be plotted.

Return type:

Figure

Heatmap and Boxplot#

Application-efficiency heatmap and boxplot visualizations.

ppbcc.plot.heatmap.HEATMAP_COLORMAP = 'viridis'#

Colormap shared by both efficiency heatmaps.

ppbcc.plot.heatmap.MISSING_COLOR = 'black'#

Fill of a cell whose paradigm was never benchmarked on the platform.

ppbcc.plot.heatmap.MISSING_LABEL = '-'#

Annotation of a cell whose paradigm was never benchmarked on the platform.

ppbcc.plot.heatmap.DOUBLE_HEATMAP_LABEL_ANGLE = 35#

Rotation of the double heatmap’s paradigm labels, in degrees.

ppbcc.plot.heatmap.DOUBLE_HEATMAP_COLUMN_PADDING = 0.12#

Inches of clear space between two neighbouring paradigm labels.

ppbcc.plot.heatmap.DOUBLE_HEATMAP_LINE_SPACING = 1.3#

Line height of a paradigm label, as a multiple of its font size.

ppbcc.plot.heatmap.DOUBLE_HEATMAP_MIN_COLUMN_WIDTH = 1.5#

Narrowest double-heatmap column, for problems with short paradigm names.

ppbcc.plot.heatmap.DOUBLE_HEATMAP_ROW_HEIGHT = 0.85#

Inches of figure height per platform row of the double heatmap.

ppbcc.plot.heatmap.DOUBLE_HEATMAP_SIDE_CHROME = 3.6#

Inches of figure width taken by the axis labels and the color bar.

ppbcc.plot.heatmap.DOUBLE_HEATMAP_VERTICAL_CHROME = 2.2#

Inches of figure height taken by the title and the axis label.

ppbcc.plot.heatmap.DOUBLE_HEATMAP_ANNOTATION_SHARE = 0.4#

Share of a column one cell value may occupy. It sets the column pitch, so a smaller share is a wider figure: at one text width that is a shorter chart whose values still print at about 5.5 pt.

ppbcc.plot.heatmap.plot_efficiency_heatmap(efficiency, problem_title, remove_description=False, selected_size='all', sort_alphabetically=False)[source]#

Plot application efficiency by platform and paradigm as a heatmap.

Duplicate application/platform observations are averaged. The color scale is fixed to the valid efficiency range so separate plots remain comparable. A paradigm that was never benchmarked on a platform is drawn as a black cell with a dash rather than as an efficiency of zero.

Parameters:
  • efficiency (DataFrame) – Rows containing application, hardware, and efficiency.

  • problem_title (str) – Benchmark problem shown in the title.

  • remove_description (bool) – Whether to hide bracketed implementation details.

  • selected_size (float | str) – Numeric problem size or size-selection literal.

  • sort_alphabetically (bool) – Whether to order paradigms by name instead of by descending mean efficiency.

Returns:

Matplotlib figure containing the heatmap.

Raises:

ValueError – If no efficiency observations are available.

Return type:

Figure

ppbcc.plot.heatmap.plot_efficiency_double_heatmap(first_efficiency, second_efficiency, problem_title, first_size, second_size, remove_description=False, sort_alphabetically=False)[source]#

Compare application efficiency at two problem sizes in one heatmap.

Every platform/paradigm cell is split along its diagonal: the upper-left triangle shows the first size, the lower-right triangle the second. Both halves share one color scale fixed to [0, 1]. A half whose paradigm was never benchmarked on the platform at that size is black with a dash.

Parameters:
  • first_efficiency (DataFrame) – Efficiency rows at the first size.

  • second_efficiency (DataFrame) – Efficiency rows at the second size.

  • problem_title (str) – Benchmark problem shown in the title.

  • first_size (float) – Problem size of the upper-left triangles.

  • second_size (float) – Problem size of the lower-right triangles.

  • remove_description (bool) – Whether to hide bracketed implementation details.

  • sort_alphabetically (bool) – Whether to order paradigms by name instead of by descending mean efficiency over both sizes.

Returns:

Matplotlib figure containing the split heatmap.

Raises:

ValueError – If either size has no efficiency observations.

Return type:

Figure

ppbcc.plot.heatmap.plot_efficiency_boxplot(efficiency, problem_title, remove_description=False, selected_size='all', application_order=None)[source]#

Plot efficiency distributions across platforms for each paradigm.

Parameters:
  • efficiency (DataFrame) – Per-size, per-platform application-efficiency observations.

  • problem_title (str) – Benchmark problem shown in the title.

  • remove_description (bool) – Whether to hide bracketed implementation details.

  • selected_size (float | str) – all or an exact numeric problem size.

  • application_order (Iterable[str] | None) – Retained for API compatibility. Boxplots always sort paradigms alphabetically.

Returns:

Matplotlib figure containing paradigm-colored boxplots and observations.

Raises:

ValueError – If no efficiency observations are available.

Return type:

Figure

Time Bar Plot#

Bar chart of benchmark runtimes per paradigm and platform.

ppbcc.plot.time_barplot.RUNTIME_NS = 'Runtime (ns)'#

nanoseconds, or FLOP when normalized.

Type:

Column of the plotted value

ppbcc.plot.time_barplot.TIME_UNITS = (('s', 1000000000.0), ('ms', 1000000.0), ('$\\mu$s', 1000.0), ('ns', 1.0))#

Display units for runtimes, largest first, with their size in nanoseconds.

ppbcc.plot.time_barplot.GROUP_FILL = 0.84#

Share of one platform group’s width filled with bars.

ppbcc.plot.time_barplot.DECIMAL_TICK_DECADES = 1.5#

Below this many decades a runtime axis gets plain decimal ticks, since Matplotlib would otherwise label it with cluttered minor ticks.

ppbcc.plot.time_barplot.plot_time_barplot(runtimes, problem_title, time_label, selected_size, precision, normalized=False, remove_description=False, show_legends=True)[source]#

Plot one runtime bar per paradigm, grouped by platform.

With a single platform the bars stand side by side and are labeled with their paradigm. With several platforms every platform is one labeled group holding a slot per paradigm, in the same order in every group, so a paradigm keeps its position; a slot stays empty where the paradigm has no result on that platform. The runtime axis is logarithmic, because runtimes of one problem differ by orders of magnitude between paradigms.

Parameters:
  • runtimes (DataFrame) – One row per application and hardware with Runtime (ns), and Runtime x Peak Performance (FLOP) when normalized.

  • problem_title (str) – Benchmark problem shown in the title.

  • time_label (str) – Name of the plotted runtime, e.g. Kernel Time.

  • selected_size (float) – Problem size the runtimes were measured at.

  • precision (int) – Floating-point precision in bits.

  • normalized (bool) – Whether the runtime is multiplied by the platform’s peak performance, i.e. plotted as the FLOPs the platform could have executed in that time.

  • remove_description (bool) – Whether bracketed descriptions are hidden.

  • show_legends (bool) – Whether the paradigm legend is drawn into the figure.

Returns:

The Matplotlib figure.

Raises:

ValueError – If there is nothing to plot.

Return type:

Figure

Styles, Legends, and Output#

Shared styles, legends, and output helpers for P3 plots.

ppbcc.plot.styles.resolve_output_path(output, problems, mode)[source]#

Resolve the plot output path and default PDF extension.

Parameters:
  • output (Path | None) – User-supplied path, or None.

  • problems (list[str]) – Resolved problem names.

  • mode (str) – Selected plot mode.

Returns:

Output path with a suffix.

Return type:

Path

ppbcc.plot.styles.font_points(key, scale=1.0)[source]#

Resolve a font-size rcParam to points and scale it.

A size rcParam may be a number or one of Matplotlib’s relative keywords such as "medium", which seaborn replaces with a number only once a theme is applied. Going through FontProperties handles both.

Parameters:
  • key (str) – Font-size rcParam name, e.g. "axes.labelsize".

  • scale (float) – Factor applied to the resolved size.

Returns:

The scaled size in points.

Return type:

float

ppbcc.plot.styles.SHORT_METRIC_NAMES = {'halstead difficulty': 'Halstead $D$', 'halstead effort': 'Halstead $E$', 'halstead program length': 'Halstead $N$', 'halstead vocabulary': 'Halstead $\\eta$', 'halstead volume': 'Halstead $V$', 'sloc': 'SLOC', 'source lines of code': 'SLOC'}#

Axis titles for the complexity metrics. The loader’s own label (“Source Lines of Code [normalized]”) is too wide for a small panel and does not say what “normalized” is relative to.

ppbcc.plot.styles.SCALING_SUFFIXES = {'absolute': '[absolute]', 'normalized': '[% of sequential C++]'}#

How each scaling mode of the complexity loader is spelled out on an axis.

ppbcc.plot.styles.short_metric_name(metric)[source]#

Turn a complexity column name into its bare symbol.

Parameters:

metric (str) – Column name from the complexity loader, for example "Halstead Difficulty [normalized]".

Returns:

A short name such as "Halstead $D$", without the scaling suffix. An unrecognised metric keeps its name part, so the caller never loses information it cannot re-derive.

Return type:

str

ppbcc.plot.styles.short_metric_label(metric)[source]#

Turn a complexity column name into a compact axis title.

Parameters:

metric (str) – Column name from the complexity loader, for example "Halstead Difficulty [normalized]".

Returns:

A short title such as "Halstead $D$ [% of sequential C++]". A metric or scaling mode that is not recognised is returned unchanged, so the caller never loses information it cannot re-derive.

Return type:

str

ppbcc.plot.styles.format_relative_log_axis(axis)[source]#

Label a logarithmic complexity axis with plain decimal ticks.

Matplotlib’s default log locator labels a range such as 100-700 as 10^2, 4x10^2, 6x10^2, which is unreadable at figure scale, and over a range such as 110-190 it places no major tick at all. Round values inside the limits are used instead, choosing the mantissa set whose tick count comes closest to _LOG_TICK_TARGET so that both a narrow and a wide range stay readable. If no set yields at least two ticks the axis is left alone rather than stripped of its labels.

Parameters:

axis – The x or y axis to format.

Return type:

None

ppbcc.plot.styles.use_inward_ticks(axes)[source]#

Keep a right-hand y axis from reading as negative numbers.

With Matplotlib’s default outward ticks a right-hand axis draws the tick mark between the spine and its label, so 1.0 reads as -1.0. Turning the ticks inward is not enough on its own under seaborn’s whitegrid style, whose spine is too faint to separate them: the labels also move further out and the spine is darkened, so the axis line is unmistakably between the tick and the number.

Parameters:

axes (Axes) – Axes whose right-hand y axis is corrected.

Return type:

None

ppbcc.plot.styles.create_separate_legend(applications, problems, platforms, remove_description=False, vertical=False)[source]#

Create a standalone paradigm/device legend.

Paradigms are placed at the top and devices at the bottom. A problem-marker section is included between them when more than one problem is plotted, and the device section is left out when no platforms are given. By default each section is a separate four-column legend; vertical mode combines the sections into one single-column legend with subheadings.

Parameters:
  • applications (list[str]) – Application labels in display order.

  • problems (list[str]) – Problem names in display order.

  • platforms (list[str]) – Hardware labels in display order.

  • remove_description (bool) – Whether bracketed descriptions are hidden.

  • vertical (bool) – Whether legend entries are arranged in one column.

Returns:

A standalone legend figure.

Return type:

Figure

ppbcc.plot.styles.save_figure(figure, output)[source]#

Save a figure, creating its parent directory if necessary.

Parameters:
  • figure (Figure) – Figure to save.

  • output (Path) – Destination path.

Return type:

None