aboutsummaryrefslogtreecommitdiff
path: root/benchmark/agbenchmark/reports/processing/graphs.py
diff options
context:
space:
mode:
Diffstat (limited to 'benchmark/agbenchmark/reports/processing/graphs.py')
-rw-r--r--benchmark/agbenchmark/reports/processing/graphs.py205
1 files changed, 205 insertions, 0 deletions
diff --git a/benchmark/agbenchmark/reports/processing/graphs.py b/benchmark/agbenchmark/reports/processing/graphs.py
new file mode 100644
index 000000000..8abe9d01a
--- /dev/null
+++ b/benchmark/agbenchmark/reports/processing/graphs.py
@@ -0,0 +1,205 @@
+from pathlib import Path
+from typing import Any
+
+import matplotlib.patches as mpatches
+import matplotlib.pyplot as plt
+import numpy as np
+import pandas as pd
+from matplotlib.colors import Normalize
+
+
+def save_combined_radar_chart(
+ categories: dict[str, Any], save_path: str | Path
+) -> None:
+ categories = {k: v for k, v in categories.items() if v}
+ if not all(categories.values()):
+ raise Exception("No data to plot")
+ labels = np.array(
+ list(next(iter(categories.values())).keys())
+ ) # We use the first category to get the keys
+ num_vars = len(labels)
+ angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()
+ angles += angles[
+ :1
+ ] # Add the first angle to the end of the list to ensure the polygon is closed
+
+ # Create radar chart
+ fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True))
+ ax.set_theta_offset(np.pi / 2) # type: ignore
+ ax.set_theta_direction(-1) # type: ignore
+ ax.spines["polar"].set_visible(False) # Remove border
+
+ # Define a custom normalization to start the color from the middle
+ norm = Normalize(
+ vmin=0, vmax=max([max(val.values()) for val in categories.values()])
+ ) # We use the maximum of all categories for normalization
+
+ cmap = plt.cm.get_cmap("nipy_spectral", len(categories)) # type: ignore
+
+ colors = [cmap(i) for i in range(len(categories))]
+
+ for i, (cat_name, cat_values) in enumerate(
+ categories.items()
+ ): # Iterating through each category (series)
+ values = np.array(list(cat_values.values()))
+ values = np.concatenate((values, values[:1])) # Ensure the polygon is closed
+
+ ax.fill(angles, values, color=colors[i], alpha=0.25) # Draw the filled polygon
+ ax.plot(angles, values, color=colors[i], linewidth=2) # Draw polygon
+ ax.plot(
+ angles,
+ values,
+ "o",
+ color="white",
+ markersize=7,
+ markeredgecolor=colors[i],
+ markeredgewidth=2,
+ ) # Draw points
+
+ # Draw legend
+ legend = ax.legend(
+ handles=[
+ mpatches.Patch(color=color, label=cat_name, alpha=0.25)
+ for cat_name, color in zip(categories.keys(), colors)
+ ],
+ loc="upper left",
+ bbox_to_anchor=(0.7, 1.3),
+ )
+
+ # Adjust layout to make room for the legend
+ plt.tight_layout()
+
+ lines, labels = plt.thetagrids(
+ np.degrees(angles[:-1]), (list(next(iter(categories.values())).keys()))
+ ) # We use the first category to get the keys
+
+ highest_score = 7
+
+ # Set y-axis limit to 7
+ ax.set_ylim(top=highest_score)
+
+ # Move labels away from the plot
+ for label in labels:
+ label.set_position(
+ (label.get_position()[0], label.get_position()[1] + -0.05)
+ ) # adjust 0.1 as needed
+
+ # Move radial labels away from the plot
+ ax.set_rlabel_position(180) # type: ignore
+
+ ax.set_yticks([]) # Remove default yticks
+
+ # Manually create gridlines
+ for y in np.arange(0, highest_score + 1, 1):
+ if y != highest_score:
+ ax.plot(
+ angles, [y] * len(angles), color="gray", linewidth=0.5, linestyle=":"
+ )
+ # Add labels for manually created gridlines
+ ax.text(
+ angles[0],
+ y + 0.2,
+ str(int(y)),
+ color="black",
+ size=9,
+ horizontalalignment="center",
+ verticalalignment="center",
+ )
+
+ plt.savefig(save_path, dpi=300) # Save the figure as a PNG file
+ plt.close() # Close the figure to free up memory
+
+
+def save_single_radar_chart(
+ category_dict: dict[str, int], save_path: str | Path
+) -> None:
+ labels = np.array(list(category_dict.keys()))
+ values = np.array(list(category_dict.values()))
+
+ num_vars = len(labels)
+
+ angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()
+
+ angles += angles[:1]
+ values = np.concatenate((values, values[:1]))
+
+ colors = ["#1f77b4"]
+
+ fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True))
+ ax.set_theta_offset(np.pi / 2) # type: ignore
+ ax.set_theta_direction(-1) # type: ignore
+
+ ax.spines["polar"].set_visible(False)
+
+ lines, labels = plt.thetagrids(
+ np.degrees(angles[:-1]), (list(category_dict.keys()))
+ )
+
+ highest_score = 7
+
+ # Set y-axis limit to 7
+ ax.set_ylim(top=highest_score)
+
+ for label in labels:
+ label.set_position((label.get_position()[0], label.get_position()[1] + -0.05))
+
+ ax.fill(angles, values, color=colors[0], alpha=0.25)
+ ax.plot(angles, values, color=colors[0], linewidth=2)
+
+ for i, (angle, value) in enumerate(zip(angles, values)):
+ ha = "left"
+ if angle in {0, np.pi}:
+ ha = "center"
+ elif np.pi < angle < 2 * np.pi:
+ ha = "right"
+ ax.text(
+ angle,
+ value - 0.5,
+ f"{value}",
+ size=10,
+ horizontalalignment=ha,
+ verticalalignment="center",
+ color="black",
+ )
+
+ ax.set_yticklabels([])
+
+ ax.set_yticks([])
+
+ if values.size == 0:
+ return
+
+ for y in np.arange(0, highest_score, 1):
+ ax.plot(angles, [y] * len(angles), color="gray", linewidth=0.5, linestyle=":")
+
+ for angle, value in zip(angles, values):
+ ax.plot(
+ angle,
+ value,
+ "o",
+ color="white",
+ markersize=7,
+ markeredgecolor=colors[0],
+ markeredgewidth=2,
+ )
+
+ plt.savefig(save_path, dpi=300) # Save the figure as a PNG file
+ plt.close() # Close the figure to free up memory
+
+
+def save_combined_bar_chart(categories: dict[str, Any], save_path: str | Path) -> None:
+ if not all(categories.values()):
+ raise Exception("No data to plot")
+
+ # Convert dictionary to DataFrame
+ df = pd.DataFrame(categories)
+
+ # Create a grouped bar chart
+ df.plot(kind="bar", figsize=(10, 7))
+
+ plt.title("Performance by Category for Each Agent")
+ plt.xlabel("Category")
+ plt.ylabel("Performance")
+
+ plt.savefig(save_path, dpi=300) # Save the figure as a PNG file
+ plt.close() # Close the figure to free up memory