code: def _make_main_metric_plot(
      df: pd.DataFrame, palette: dict, opponent: str, outpath: Path
  ) -> None:
      #   Calculate error bars
      error_bars = {}
      for ix, row in df.iterrows():
          winrate = row["player_0_win_ratio"]
          # standard error of the mean (SEM) for binary variables
          # sqrt(p * (1 - p) / n)
          sem = (winrate * (1 - winrate) / row["num_rounds"]) ** 0.5
          error_bars[ix] = (winrate - 2 * sem, winrate + 2 * sem)
  
      #   Duplicate the rows so that `errorbar=func` argument in `sns.catplot` works.
      #   This is a super-ugly fix, but is probably "cleanest" from the POV of the
      #   amount of code written.
      duplicated_rows_df = pd.concat([df, df], ignore_index=True)
  
      g = sns.catplot(
          data=duplicated_rows_df,
          kind="bar",
          legend=False,
          x="player_0",
          y="player_0_win_ratio",
          errorbar=lambda x: error_bars[x.index[0]],
          errwidth=1,
          capsize=0.1,
          palette=palette,
          aspect=1.5,
      )
      g.set(ylim=(0, 1))
      g.despine(left=True)
      g.set(title=f"Win ratio against {opponent}")
      g.set(xlabel=None, ylabel="% of rounds won")
      plt.tight_layout()
      plt.savefig(outpath)
      plt.show()
  
file_path: evals/evals/elsuite/bluff/scripts/make_plots.py
imports: import argparse
  from pathlib import Path
  import matplotlib.pyplot
  import pandas
  import seaborn
  from evals.utils import log_utils
label_desc: Use image node_id 3 for calling a global function with example usage: _make_main_metric_plot(df, palette, opponent, outpath) without return types