{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib\n",
    "from matplotlib.lines import Line2D\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib.patches as mpatches\n",
    "import seaborn as sns\n",
    "\n",
    "matplotlib.rc('font',family='serif', serif=['Palatino'])\n",
    "sns.set(font='serif', font_scale=1.4)\n",
    "sns.set_style(\"white\", {\n",
    "        \"font.family\": \"serif\",\n",
    "        \"font.weight\": \"normal\",\n",
    "        \"font.serif\": [\"Times\", \"Palatino\", \"serif\"],\n",
    "        'axes.facecolor': 'white',\n",
    "        'lines.markeredgewidth': 1})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_nested_piechart(data, plot_title, legend_title):\n",
    "    # Prepare outer and inner data\n",
    "    outer_labels = list(data.keys())  # Outer labels are the main groups\n",
    "    outer_data = [sum(group['values']) for group in data.values()]  # Sum of each group's subcategories\n",
    "    outer_colors = [group['colors'][0] for group in data.values()]  # Use the first color of each group for the outer layer\n",
    "\n",
    "    # Flatten subcategory labels, values, and colors\n",
    "    inner_labels = [subcategory for group_data in data.values() for subcategory in group_data['subcategories']]\n",
    "    inner_data = [value for group_data in data.values() for value in group_data['values']]\n",
    "    inner_colors = [color for group_data in data.values() for color in group_data['subcategory_colors']]\n",
    "\n",
    "    # Create the plot\n",
    "    fig, ax = plt.subplots()\n",
    "\n",
    "    # Outer pie chart (larger donut) with labels but no percentages\n",
    "    size = 0.3\n",
    "    wedges, texts = ax.pie(outer_data, radius=1, labels=outer_labels, colors=outer_colors, \n",
    "                           wedgeprops=dict(width=size, edgecolor='w'), startangle=90, labeldistance=0.85)\n",
    "\n",
    "    # Inner pie chart (smaller donut) with percentages and no labels\n",
    "    wedges, texts, autotexts = ax.pie(inner_data, radius=1-size, labels=None, colors=inner_colors, \n",
    "                                     autopct='%1.1f%%', wedgeprops=dict(width=size, edgecolor='w'), \n",
    "                                     startangle=90, labeldistance=None, pctdistance=0.75)\n",
    "\n",
    "    # Adjust the appearance of percentage labels\n",
    "    for autotext in autotexts:\n",
    "        autotext.set_fontsize(8)     # Set text size to a slightly smaller value\n",
    "    \n",
    "    # Create custom legend handles\n",
    "    handles = [mpatches.Patch(color=color) for color in inner_colors]\n",
    "    \n",
    "    # Add legend for inner pie chart, positioned outside the plot\n",
    "    ax.legend(handles, inner_labels, loc='center left', bbox_to_anchor=(1.05, 0.5), title=legend_title, \n",
    "              handletextpad=1, fontsize='small', title_fontsize='13')\n",
    "\n",
    "    # Add title\n",
    "    plt.title(plot_title)\n",
    "\n",
    "    # Equal aspect ratio ensures the pie chart is drawn as a circle\n",
    "    ax.set(aspect=\"equal\")\n",
    "\n",
    "    # Display the plot\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 95404 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "synchronous_piechart_data = {\n",
    "    'S': {\n",
    "        'values': [2],\n",
    "        'subcategories': ['[S] Misunderstands Predicates'],\n",
    "        'colors': ['#009E73'],\n",
    "        'subcategory_colors': ['#009E73']  # Single color, same as main category color\n",
    "    },\n",
    "    'T': {\n",
    "        'values': [3, 13, 1],\n",
    "        'subcategories': [\"[T] Violates 'Hold one item' rule\", \"[T] Violates 'One item at station' rule\", '[T] Violates both rules'],\n",
    "        'colors': ['#56B4E9'],  # Main category color\n",
    "        'subcategory_colors': ['#8CC9F1', '#56B4E9', '#2C8DAB']  # Different shades\n",
    "    },\n",
    "    'G': {\n",
    "        'values': [15, 4, 2, 13],\n",
    "        'subcategories': ['[G] Bad Start', '[G] Both Uncertainties', '[G] Ingredient Uncertainty', '[G] Order Uncertainty'],\n",
    "        'colors': ['#E69F00'],  # Main category color\n",
    "        'subcategory_colors': ['#F5C555', '#E69F00', '#BF6F00', '#9F4F00']  # Different shades\n",
    "    }\n",
    "}\n",
    "\n",
    "plot_nested_piechart(synchronous_piechart_data, 'Synchronous Failure Cases', \"Failures\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 95744 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "asynchronous_piechart_data = {\n",
    "    'S': {\n",
    "        'values': [9],\n",
    "        'subcategories': ['[S] Misunderstands Predicates'],\n",
    "        'colors': ['#009E73'],\n",
    "        'subcategory_colors': ['#009E73']\n",
    "    },\n",
    "    'A': {\n",
    "        'values': [3],\n",
    "        'subcategories': ['[A] Invalid Action'],\n",
    "        'colors': ['#ff9999'],\n",
    "        'subcategory_colors': ['#ff9999']\n",
    "    },\n",
    "    'T': {\n",
    "        'values': [3, 49],\n",
    "        'subcategories': [\"[T] Violates 'Hold one item' rule\", \"[T] Violates 'One item at station' rule\"],\n",
    "        'colors': ['#56B4E9'],\n",
    "        'subcategory_colors': ['#8CC9F1', '#56B4E9']\n",
    "    },\n",
    "    'G': {\n",
    "        'values': [9, 1, 11, 4],\n",
    "        'subcategories': ['[G] Bad Start', '[G] Both Uncertainties', '[G] Ingredient Uncertainty', '[G] Order Uncertainty'],\n",
    "        'colors': ['#E69F00'],\n",
    "        'subcategory_colors': ['#F5C555', '#E69F00', '#BF6F00', '#9F4F00']\n",
    "    }\n",
    "}\n",
    "\n",
    "plot_nested_piechart(asynchronous_piechart_data, 'Asynchronous Failure Cases', \"Failures\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_nested_piecharts(data1, data2, plot_titles, legend_title):\n",
    "    # Prepare the outer and inner data for both pie charts\n",
    "    def prepare_pie_data(data):\n",
    "        outer_labels = list(data.keys())  # Outer labels are the main groups\n",
    "        outer_data = [sum(group['values']) for group in data.values()]  # Sum of each group's subcategories\n",
    "        outer_colors = [group['colors'][0] for group in data.values()]  # First color of each group for the outer layer\n",
    "        \n",
    "        # Flatten subcategory labels, values, and colors\n",
    "        inner_labels = [subcategory for group_data in data.values() for subcategory in group_data['subcategories']]\n",
    "        inner_data = [value for group_data in data.values() for value in group_data['values']]\n",
    "        inner_colors = [color for group_data in data.values() for color in group_data['subcategory_colors']]\n",
    "        \n",
    "        return outer_labels, outer_data, outer_colors, inner_labels, inner_data, inner_colors\n",
    "    \n",
    "    # Prepare the data for both subplots\n",
    "    outer_labels1, outer_data1, outer_colors1, inner_labels1, inner_data1, inner_colors1 = prepare_pie_data(data1)\n",
    "    outer_labels2, outer_data2, outer_colors2, inner_labels2, inner_data2, inner_colors2 = prepare_pie_data(data2)\n",
    "    \n",
    "    # Create subplots\n",
    "    fig, axes = plt.subplots(1, 2, figsize=(12, 6))  # 1 row, 2 columns of subplots\n",
    "    \n",
    "    # Define a helper function to plot individual nested pie charts\n",
    "    def plot_pie(ax, outer_labels, outer_data, outer_colors, inner_labels, inner_data, inner_colors, title):\n",
    "        size = 0.3\n",
    "        # Outer pie chart (larger donut) with labels but no percentages\n",
    "        wedges, texts = ax.pie(outer_data, radius=1, labels=outer_labels, colors=outer_colors, \n",
    "                               wedgeprops=dict(width=size, edgecolor='w'), startangle=90, labeldistance=0.85)\n",
    "\n",
    "        # Inner pie chart (smaller donut) with percentages and no labels\n",
    "        wedges, texts, autotexts = ax.pie(inner_data, radius=1-size, labels=None, colors=inner_colors, \n",
    "                                         autopct='%1.1f%%', wedgeprops=dict(width=size, edgecolor='w'), \n",
    "                                         startangle=90, labeldistance=None, pctdistance=0.75)\n",
    "        \n",
    "        # Adjust the appearance of percentage labels\n",
    "        for autotext in autotexts:\n",
    "            autotext.set_fontsize(14)  # Increased text size\n",
    "            autotext.set_weight('bold')  # Set text weight to bold\n",
    "\n",
    "        # Add title with larger font size\n",
    "        ax.set_title(title, fontsize=16)  # Increased title font size\n",
    "        ax.set(aspect=\"equal\")  # Equal aspect ratio ensures the pie chart is drawn as a circle\n",
    "\n",
    "        # Calculate the total and place it in the center\n",
    "        total = sum(outer_data)\n",
    "        ax.text(0, 0, f'Total: {total}', ha='center', va='center', fontsize=16, weight='bold')  # Increased font size\n",
    "\n",
    "    # Plot the first pie chart in the first subplot\n",
    "    plot_pie(axes[0], outer_labels1, outer_data1, outer_colors1, inner_labels1, inner_data1, inner_colors1, plot_titles[0])\n",
    "\n",
    "    # Plot the second pie chart in the second subplot\n",
    "    plot_pie(axes[1], outer_labels2, outer_data2, outer_colors2, inner_labels2, inner_data2, inner_colors2, plot_titles[1])\n",
    "\n",
    "    # Combine all inner labels and colors\n",
    "    combined_inner_labels = inner_labels1 + inner_labels2\n",
    "    combined_inner_colors = inner_colors1 + inner_colors2\n",
    "\n",
    "    # Create a dictionary to ensure unique labels and their corresponding colors\n",
    "    unique_legend = {label: color for label, color in zip(combined_inner_labels, combined_inner_colors)}\n",
    "    \n",
    "    # Create custom legend handles for unique labels\n",
    "    handles = [mpatches.Patch(color=color) for color in unique_legend.values()]\n",
    "    \n",
    "    # Add shared legend outside the plot with unique labels\n",
    "    fig.legend(handles, unique_legend.keys(), loc='center left', bbox_to_anchor=(1.05, 0.5), title=legend_title, \n",
    "               handletextpad=1, fontsize='large', title_fontsize='18')  # Increased legend font size\n",
    "    \n",
    "    # Adjust layout so that the subplots and legend do not overlap\n",
    "    plt.tight_layout()\n",
    "    \n",
    "    # Display the plot\n",
    "    plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 218152 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_nested_piecharts(synchronous_piechart_data, asynchronous_piechart_data, ['Synchronous', 'Asynchronous'], \"Failures\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_repeated_transitions_histogram_plots(data1_successes, data1_failures, data1_label, \n",
    "                                    data2_successes, data2_failures, data2_label, \n",
    "                                    x_label, bins=None, xtick_increment=1):\n",
    "    # Set bin_width to 1\n",
    "    bin_width = 1\n",
    "\n",
    "    # Calculate bin edges\n",
    "    if bins is None:\n",
    "        bin_edges = np.arange(min(min(data1_failures), min(data2_failures)), max(max(data1_failures), max(data2_failures)) + bin_width + 1, bin_width) - 0.5\n",
    "    else:\n",
    "        all_data_failures = np.concatenate([data1_failures, data2_failures])\n",
    "        bin_edges = np.histogram_bin_edges(all_data_failures, bins)\n",
    "\n",
    "    # Set global font size for the plot\n",
    "    plt.rcParams.update({'font.size': 14})\n",
    "\n",
    "    # Create subplots\n",
    "    fig, axs = plt.subplots(1, 2, figsize=(14, 6), sharey=True)\n",
    "\n",
    "    # Color-blind friendly colors\n",
    "    cbf_colors = ['#DC267F', '#785EF0']  # Red (failures) and Purple (successes)\n",
    "\n",
    "    # Plot stacked histogram for data1\n",
    "    bars1 = axs[0].hist([data1_failures, data1_successes], bins=bin_edges, alpha=0.7, color=cbf_colors, edgecolor='black', stacked=True)\n",
    "    axs[0].set_xlabel(x_label, fontsize=18)\n",
    "    axs[0].set_ylabel('Frequency', fontsize=18)\n",
    "    axs[0].set_title(data1_label, fontsize=20)\n",
    "\n",
    "    # Set x-ticks with custom increments for data1\n",
    "    xticks = np.arange(min(bin_edges) + bin_width / 2, max(bin_edges), xtick_increment)\n",
    "    axs[0].set_xticks(xticks)\n",
    "    axs[0].set_xticklabels(xticks.astype(int), fontsize=16)\n",
    "\n",
    "    # Plot stacked histogram for data2\n",
    "    bars2 = axs[1].hist([data2_failures, data2_successes], bins=bin_edges, alpha=0.7, color=cbf_colors, edgecolor='black', stacked=True)\n",
    "    axs[1].set_xlabel(x_label, fontsize=18)\n",
    "    axs[1].set_title(data2_label, fontsize=20)\n",
    "\n",
    "    # Set x-ticks with custom increments for data2\n",
    "    axs[1].set_xticks(xticks)\n",
    "    axs[1].set_xticklabels(xticks.astype(int), fontsize=16)\n",
    "\n",
    "    # Add legend\n",
    "    bar_labels = ['Failures', 'Successes']\n",
    "    bar_artists1 = [bars1[2][0], bars1[2][1]]  # Extract the bars from the hist output (patches)\n",
    "    bar_artists2 = [bars2[2][0], bars2[2][1]]\n",
    "\n",
    "    # Calculate 50% point and mean of each half for failure data only\n",
    "    half1_data1_failures = data1_failures[:len(data1_failures)//2]\n",
    "    half2_data1_failures = data1_failures[len(data1_failures)//2:]\n",
    "    half1_mean_data1_failures = np.mean(half1_data1_failures)\n",
    "    half2_mean_data1_failures = np.mean(half2_data1_failures)\n",
    "    mid_point_data1_failures = np.median(data1_failures)\n",
    "\n",
    "    half1_data2_failures = data2_failures[:len(data2_failures)//2]\n",
    "    half2_data2_failures = data2_failures[len(data2_failures)//2:]\n",
    "    half1_mean_data2_failures = np.mean(half1_data2_failures)\n",
    "    half2_mean_data2_failures = np.mean(half2_data2_failures)\n",
    "    mid_point_data2_failures = np.median(data2_failures)\n",
    "\n",
    "    # Plot dashed lines and add annotations for data1 (failures only)\n",
    "    axs[0].axvline(mid_point_data1_failures, color='black', linestyle='--')\n",
    "    axs[0].text(mid_point_data1_failures + 0.2, max(axs[0].get_ylim())*0.8, f'{mid_point_data1_failures:.2f}', \n",
    "                color='black', ha='left', fontsize=16, bbox=dict(facecolor='white', alpha=0.7))\n",
    "    axs[0].axvline(half1_mean_data1_failures, color='grey', linestyle='--')\n",
    "    axs[0].text(half1_mean_data1_failures - 1.6, max(axs[0].get_ylim())*0.7, f'{half1_mean_data1_failures:.2f}', \n",
    "                color='grey', ha='left', fontsize=16, bbox=dict(facecolor='white', alpha=0.7))\n",
    "    axs[0].axvline(half2_mean_data1_failures, color='grey', linestyle='--')\n",
    "    axs[0].text(half2_mean_data1_failures + 0.2, max(axs[0].get_ylim())*0.6, f'{half2_mean_data1_failures:.2f}', \n",
    "                color='grey', ha='left', fontsize=16, bbox=dict(facecolor='white', alpha=0.7))\n",
    "\n",
    "    # Plot dashed lines and add annotations for data2 (failures only)\n",
    "    axs[1].axvline(mid_point_data2_failures, color='black', linestyle='--')\n",
    "    axs[1].text(mid_point_data2_failures + 0.2, max(axs[1].get_ylim())*0.8, f'{mid_point_data2_failures:.2f}', \n",
    "                color='black', ha='left', fontsize=16, bbox=dict(facecolor='white', alpha=0.7))\n",
    "    axs[1].axvline(half1_mean_data2_failures, color='grey', linestyle='--')\n",
    "    axs[1].text(half1_mean_data2_failures - 1.6, max(axs[1].get_ylim())*0.7, f'{half1_mean_data2_failures:.2f}', \n",
    "                color='grey', ha='left', fontsize=16, bbox=dict(facecolor='white', alpha=0.7))\n",
    "    axs[1].axvline(half2_mean_data2_failures, color='grey', linestyle='--')\n",
    "    axs[1].text(half2_mean_data2_failures + 0.2, max(axs[1].get_ylim())*0.6, f'{half2_mean_data2_failures:.2f}', \n",
    "                color='grey', ha='left', fontsize=16, bbox=dict(facecolor='white', alpha=0.7))\n",
    "\n",
    "    # Custom dashed lines for the legend\n",
    "    custom_lines = [Line2D([0], [0], color='black', linestyle='--', lw=2),\n",
    "                    Line2D([0], [0], color='grey', linestyle='--', lw=2)]\n",
    "    custom_lines_labels = ['Median (failures)', 'Quartiles (failures)']\n",
    "    \n",
    "    # Add dashed lines and bar artists to the legend (for both subplots)\n",
    "    axs[0].legend(bar_artists1 + custom_lines, bar_labels + custom_lines_labels, loc='upper right', fontsize=14)\n",
    "    axs[1].legend(bar_artists2 + custom_lines, bar_labels + custom_lines_labels, loc='upper right', fontsize=14)\n",
    "    \n",
    "    # Show plot\n",
    "    plt.tight_layout()\n",
    "    plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 81224 characters]",
      "text/plain": [
       "<Figure size 1400x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "synchronous_success_repeated_actions = [\n",
    "    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,\n",
    "    2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 6, 3,\n",
    "    0, 0\n",
    "]\n",
    "synchronous_failures_repeated_actions = [\n",
    "    2, 2, 2, 0, 1, 4, 4, 0, 1, 2, 2, 2, 0, 4, 1, 2, 2, 6, 2, 3, 2, 4,\n",
    "    4, 2, 5, 7, 3, 3, 1, 1, 11, 14, 8, 11, 7, 10, 7, 6, 11, 15, 2, 9,\n",
    "    10, 15, 13, 12, 6, 9, 1, 6, 3, 12, 11\n",
    "]\n",
    "asynchronous_success_repeated_actions = [\n",
    "    0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 2\n",
    "]\n",
    "asynchronous_failures_repeated_actions = [\n",
    "    3, 4, 5, 4, 3, 8, 2, 4, 3, 5, 1, 7, 1, 10, 3, 2, 2, 4, 9, 1, 6, 4,\n",
    "    14, 8, 3, 7, 7, 3, 9, 2, 5, 11, 6, 8, 7, 14, 8, 8, 5, 3, 1, 4, 0,\n",
    "    3, 2, 4, 6, 1, 5, 1, 11, 12, 10, 13, 2, 6, 12, 16, 14, 6, 10, 10,\n",
    "    11, 7, 3, 14, 9, 4, 18, 15, 15, 22, 17, 17, 14, 22, 12, 22, 14, 10,\n",
    "    20, 13, 24, 14, 24, 29, 9, 18, 26\n",
    "]\n",
    "\n",
    "plot_repeated_transitions_histogram_plots(\n",
    "    synchronous_success_repeated_actions, synchronous_failures_repeated_actions, 'Synchronous',\n",
    "    asynchronous_success_repeated_actions, asynchronous_failures_repeated_actions, 'Asynchronous',\n",
    "    'Repeated Transitions', xtick_increment=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_binned_histogram(bins, labels, x_label, data1, title1, colors1, data2, title2, colors2):\n",
    "    # Ensure the number of labels and colors matches the number of bins - 1\n",
    "    assert len(labels) == len(bins) - 1, \"The number of labels must match the number of bins minus 1.\"\n",
    "    assert len(colors1) == len(bins) - 1, \"The number of colors for data1 must match the number of bins minus 1.\"\n",
    "    assert len(colors2) == len(bins) - 1, \"The number of colors for data2 must match the number of bins minus 1.\"\n",
    "\n",
    "    # Bin the data\n",
    "    hist1, _ = np.histogram(data1, bins=bins)\n",
    "    hist2, _ = np.histogram(data2, bins=bins)\n",
    "\n",
    "    # Calculate total counts for percentage calculation\n",
    "    total1 = np.sum(hist1)\n",
    "    total2 = np.sum(hist2)\n",
    "\n",
    "    # Calculate percentages\n",
    "    percent1 = (hist1 / total1) * 100 if total1 > 0 else np.zeros_like(hist1)\n",
    "    percent2 = (hist2 / total2) * 100 if total2 > 0 else np.zeros_like(hist2)\n",
    "\n",
    "    # Increase the font size for readability\n",
    "    plt.rcParams.update({'font.size': 14})  # Global font size adjustment\n",
    "\n",
    "    # Create subplots\n",
    "    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))  # Two plots side by side with larger figure size\n",
    "\n",
    "    # Plotting the first histogram (left)\n",
    "    bars1 = ax1.bar(labels, percent1, color=colors1)  # Plot percentages directly\n",
    "    ax1.set_xlabel(x_label, fontsize=18)\n",
    "    ax1.set_ylabel('Percentage (%)', fontsize=18)\n",
    "    ax1.set_title(title1, fontsize=20)\n",
    "\n",
    "    # Annotate percentages above bars in the first histogram\n",
    "    for bar, percent in zip(bars1, percent1):\n",
    "        ax1.text(bar.get_x() + bar.get_width() / 2, bar.get_height(), f'{percent:.1f}%', \n",
    "                 ha='center', va='bottom', fontsize=16, fontweight='bold')\n",
    "\n",
    "    # Plotting the second histogram (right)\n",
    "    bars2 = ax2.bar(labels, percent2, color=colors2)  # Plot percentages directly\n",
    "    ax2.set_xlabel(x_label, fontsize=18)\n",
    "    ax2.set_ylabel('Percentage (%)', fontsize=18)\n",
    "    ax2.set_title(title2, fontsize=18)\n",
    "\n",
    "    # Annotate percentages above bars in the second histogram\n",
    "    for bar, percent in zip(bars2, percent2):\n",
    "        ax2.text(bar.get_x() + bar.get_width() / 2, bar.get_height(), f'{percent:.1f}%', \n",
    "                 ha='center', va='bottom', fontsize=16, fontweight='bold')\n",
    "\n",
    "    # Set the y-axis limits for both subplots\n",
    "    ax1.set_ylim(0, 100)\n",
    "    ax2.set_ylim(0, 100)\n",
    "\n",
    "    plt.tight_layout()\n",
    "    plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 54712 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "bins = [1, 1.0001, 1.25, 1.5]\n",
    "labels = ['1', '(1, 1.25]', '(1.25, 1.5]']\n",
    "synchronous_optimality = [\n",
    "    1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.36,\n",
    "    1.07, 1.00, 1.00, 1.00, 1.14, 1.08, 1.00, 1.11, 1.00, 1.42,\n",
    "    1.00, 1.33, 1.38, 1.00, 1.20, 1.20, 1.00, 1.00, 1.17, 1.20,\n",
    "    1.00, 1.27, 1.00, 1.13, 1.00, 1.00, 1.31, 1.00, 1.07, 1.00,\n",
    "    1.50, 1.00, 1.21, 1.29, 1.41, 1.00, 1.02\n",
    "]\n",
    "asynchronous_optimality = [\n",
    "    1.29, 1.18, 1.04, 1.20, 1.00, 1.09, 1.14, 1.27, 1.19, 1.05, 1.50\n",
    "]\n",
    "plot_binned_histogram(bins, labels, \"Optimality Ratio\",\n",
    "    synchronous_optimality, \"Synchronous\", ['#785EF0', '#648FFF', '#FE6100'],\n",
    "    asynchronous_optimality, \"Asynchronous\", ['#785EF0', '#648FFF', '#FE6100']\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 64284 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "bins = [0.0001, 0.5, 1.0, 1.5, np.inf]\n",
    "labels = ['(0, 0.5]', '(0.5, 1.0]', '(1.0, 1.5]', '(1.5, ∞)']\n",
    "synchronous_step_to_go_ratios = [\n",
    "    1.40, 0.80, 0.40, 0.57, 1.29, 1.08, 0.63, 0.80, 2.20, 2.00, 1.40, 1.20,\n",
    "    1.30, 1.60, 1.07, 0.93, 1.07, 1.04, 1.04, 0.96, 1.13, 0.96, 1.22, 1.04,\n",
    "    1.39, 0.03, 1.11, 0.89, 0.78, 1.19, 0.84, 0.93, 0.18, 1.00, 0.55, 1.00,\n",
    "    0.82, 0.29, 0.89, 0.46, 0.65, 0.41, 1.30, 0.98, 0.63, 0.60, 0.84, 0.56,\n",
    "    0.61, 1.19, 0.42, 1.28, 0.81\n",
    "]\n",
    "asynchronous_step_to_go_ratios = [\n",
    "    0.67, 0.76, 0.76, 0.95, 1.00, 0.76, 0.76, 1.00, 0.59, 0.63, 0.67, 0.67,\n",
    "    0.81, 0.67, 1.26, 0.81, 0.92, 0.76, 1.03, 0.59, 0.86, 0.52, 0.64, 1.07,\n",
    "    0.50, 0.33, 0.62, 0.38, 0.62, 0.69, 0.65, 0.54, 0.50, 0.80, 0.70, 0.78,\n",
    "    0.35, 0.37, 0.41, 0.98, 0.32, 1.37, 0.05, 1.37, 0.47, 0.16, 1.26, 0.16,\n",
    "    1.26, 0.36, 0.79, 1.05, 0.93, 0.86, 0.64, 0.86, 1.00, 0.95, 1.12, 0.48,\n",
    "    0.67, 0.67, 1.02, 0.67, 0.59, 0.89, 1.15, 0.11, 1.20, 0.82, 0.96, 1.04,\n",
    "    0.72, 0.75, 1.04, 1.22, 0.84, 0.93, 0.90, 0.27, 0.77, 0.68, 1.06, 1.09,\n",
    "    0.80, 1.02, 1.21\n",
    "]\n",
    "plot_binned_histogram(bins, labels, \"Normalized Steps to Go\",\n",
    "    synchronous_step_to_go_ratios, \"Synchronous\", ['#785EF0', '#648FFF', '#FE6100', '#DC267F'],\n",
    "    asynchronous_step_to_go_ratios, \"Asynchronous\", ['#785EF0', '#648FFF', '#FE6100', '#DC267F']\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 188276 characters]",
      "text/plain": [
       "<Figure size 1200x600 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "async_before_piechart_data = {\n",
    "    'S': {\n",
    "        'values': [5],\n",
    "        'subcategories': ['[S] Misunderstands Predicates'],\n",
    "        'colors': ['#009E73'],\n",
    "        'subcategory_colors': ['#009E73']  # Single color, same as main category color\n",
    "    },\n",
    "    'A': {\n",
    "        'values': [1],\n",
    "        'subcategories': [\"[A] Invalid Action\"],\n",
    "        'colors': ['#ff9999'],  # Main category color\n",
    "        'subcategory_colors': ['#ff9999']  # Different shades\n",
    "    },\n",
    "    'T': {\n",
    "        'values': [1, 8],\n",
    "        'subcategories': [\"[T] Violates 'Hold one item' rule\", \"[T] Violates 'One item at station' rule\"],\n",
    "        'colors': ['#56B4E9'],  # Main category color\n",
    "        'subcategory_colors': ['#8CC9F1', '#56B4E9']  # Different shades\n",
    "    },\n",
    "    'G': {\n",
    "        'values': [4, 1, 1],\n",
    "        'subcategories': ['[G] Ingredient Uncertainty', '[G] Order Uncertainty', '[G] Both Uncertainties'],\n",
    "        'colors': ['#E69F00'],  # Main category color\n",
    "        'subcategory_colors': ['#F5C555', '#E69F00', '#BF6F00']  # Different shades\n",
    "    }\n",
    "}\n",
    "\n",
    "async_after_piechart_data = {\n",
    "    'S': {\n",
    "        'values': [7],\n",
    "        'subcategories': ['[S] Misunderstands Predicates'],\n",
    "        'colors': ['#009E73'],\n",
    "        'subcategory_colors': ['#009E73']  # Single color, same as main category color\n",
    "    },\n",
    "    'T': {\n",
    "        'values': [1, 4],\n",
    "        'subcategories': [\"[T] Violates 'Hold one item' rule\", \"[T] Violates 'One item at station' rule\"],\n",
    "        'colors': ['#56B4E9'],  # Main category color\n",
    "        'subcategory_colors': ['#8CC9F1', '#56B4E9']  # Different shades\n",
    "    },\n",
    "    'G': {\n",
    "        'values': [3, 2, 1],\n",
    "        'subcategories': ['[G] Ingredient Uncertainty', '[G] Order Uncertainty', '[G] Both Uncertainties'],\n",
    "        'colors': ['#E69F00'],  # Main category color\n",
    "        'subcategory_colors': ['#F5C555', '#E69F00', '#BF6F00']  # Different shades\n",
    "    }\n",
    "}\n",
    "plot_nested_piecharts(async_before_piechart_data, async_after_piechart_data, ['Async | gpt-4o ReAct', 'Async | gpt-4o ReAct + Prior'], \"Failures\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "robotouille",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
