Source code for ppbcc.plot.navchart

"""Navchart plotting for complexity and performance portability."""

from __future__ import annotations

import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.ticker import EngFormatter

from ppbcc.constants import APPLICATION, PERFORMANCE_PORTABILITY, PROBLEM
from ppbcc.plot.styles import (
    PP_SYMBOL,
    SCATTER_MARKER_AREA,
    _application_legend_handles,
    _framework_colors,
    _problem_legend_handles,
    _problem_markers,
    short_metric_label,
)


[docs] def plot_navchart( data: pd.DataFrame, metric: str, problem_title: str, remove_description: bool = False, log_complexity: bool = False, show_legends: bool = True, ) -> plt.Figure: """Create a Navchart of complexity and performance portability. Args: data: Matched problem, application, PP, and complexity data. metric: Complexity metric column and x-axis label. problem_title: Problem name or names used in the title. remove_description: Whether to hide bracketed legend descriptions. log_complexity: Whether the complexity axis is logarithmic. show_legends: Whether legends are embedded in the plot. Returns: The Matplotlib figure. """ applications = list(dict.fromkeys(data[APPLICATION])) problems = list(dict.fromkeys(data[PROBLEM])) colors = _framework_colors(applications, remove_description) markers = _problem_markers(problems) figure, axis = plt.subplots(figsize=(9.5, 7.2)) for _, row in data.iterrows(): application = str(row[APPLICATION]) problem = str(row[PROBLEM]) marker = markers[problem] marker_options = ( {"linewidth": 1.2} if marker in {"x", "+", "1", "2", "3", "4", "|", "_"} else {"edgecolor": "black", "linewidth": 0.5} ) axis.scatter( row[metric], row[PERFORMANCE_PORTABILITY], color=colors[application], marker=marker, s=SCATTER_MARKER_AREA, zorder=3, **marker_options, ) axis.set_xlabel(short_metric_label(metric)) axis.set_ylabel(PP_SYMBOL) axis.set_ylim(0.0, 1.05) figure.suptitle(f"{problem_title} {PP_SYMBOL} - Code Complexity") if log_complexity: axis.set_xscale("log") else: axis.xaxis.set_major_formatter(EngFormatter()) axis.grid(True, linestyle="--", alpha=0.45) if show_legends: application_legend = figure.legend( handles=_application_legend_handles( applications, colors, remove_description ), title="Paradigm", loc="center left", bbox_to_anchor=(0.72, 0.55), frameon=True, ) figure.add_artist(application_legend) if len(problems) > 1: figure.legend( handles=_problem_legend_handles(problems, markers), title="Problem", loc="lower center", bbox_to_anchor=(0.34, 0.01), ncol=len(problems), frameon=True, ) figure.subplots_adjust(right=0.68, bottom=0.28 if len(problems) > 1 else 0.11) else: figure.subplots_adjust(right=0.96, bottom=0.11) return figure