text: import re
  import pandas as pd
  from scipy.stats import beta, entropy
  from scipy.special import loggamma, digamma
  import random
  import numpy as np
  # from compute_metrics import exp
  
  
  def exp(x, a=10):
      return 1 - (a ** (-1 * x))
  
  def kl(p, q):
      return entropy([p, 1-p], [q, 1-q])
  
  
  def fit_beta(data):
      EPSILON = 1e-3
      data = [EPSILON if d==0 else 1-EPSILON if d==1 else d for d in data]    # make sure no data points EQUAL one of the bounds
      if len(set(data)) == 1:     # make sure not all data points are identical
          data = [d + random.normalvariate(0, 1e-5) for d in data]
      try:
          params = beta.fit(data, floc=0, fscale=1)
      except Exception:
          pass
      return params[0], params[1]
  
  
  def fit_beta_mean_uncertainty(mean, var):
      """
      Compute parameters from the mean and variance following this parameterization:
      https://en.wikipedia.org/wiki/Beta_distribution#Mean_and_variance
      """
      EPSILON = 1E-2
      mean = EPSILON if mean==0 else 1-EPSILON if mean==1 else mean
      nu = -1 + (mean * (1 - mean)) / var
      alpha = mean * nu
      beta = (1 - mean) * nu
      if alpha < 0 or beta < 0:
          pass
      return alpha, beta
  
  def kl_dirichlet(Q, P):
      """
      Compute KL(Q; P) divergence of 2 dirichlet distributions with parameters Q and P.
      As usual, with KL(Q; P) Q represents the posterior, and P the prior.
      When these are beta distributions, Q[0] = \alpha, Q[1] = \beta.
      """
      return loggamma(sum(Q)) - loggamma(sum(P)) + \
          sum([loggamma(p) - loggamma(q) for p, q in zip(P, Q)]) + \
          sum([(q - p) * (digamma(q) - digamma(sum(Q))) for p, q in zip(P, Q)])
  
  
  def map_certainty_to_variance(certainty):
      """
      Let's just fit a line with these endpoints:
      7 --> 0.001
      1 --> 0.07 (the max possible value, when \alpha=\beta=1, is 0.08133333)
      """
      return 0.0815 - (0.0115 * certainty)
  
  
  
  # def exponentiate(df, field, steps=1000, max_alpha=100):
  # # TODO
  #     alphas = np.linspace(0, max_alpha, steps)[1:]
  
  
  ## MAIN ###
  
  if __name__ == "__main__":
      MTURK_RESULTS = "analyzed_results_combined.jsonl"
      JULY_RESULTS = "july-data-combined.csv"
      df_mturk = pd.read_json(MTURK_RESULTS, lines=True, orient="records")
      df_july = pd.read_csv(JULY_RESULTS, header=0)
  
      # clean up column names in july data
      columns = ["prior-probability", "prior-certainty", "posterior-probability", "posterior-certainty", "Notes"]
      df_july = df_july[columns]
      df_july = df_july.rename({x: re.sub(r"-", "_", x) + "_july" for x in columns}, axis=1)
      df = pd.concat([df_mturk, df_july], axis=1)
  
      # Compute beta stuff for mturk data
      for field in ["prior", "posterior"]:
          df[field + "_beta"] = df[field].apply(fit_beta)
      df["kl_beta_mturk"] = df.apply(lambda x: kl_dirichlet(x["posterior_beta"], x["prior_beta"]), axis=1)
      # df["kl_beta_exp_mturk"] = df.apply(lambda x: exp(x["kl_beta_mturk"]), axis=1)
  
      # Compute prior and posterior with july and mturk data
      for field in ["prior", "posterior"]:
          a = 0.45
          df[field + "_mturk_july"] = a * df[field + "_mean"] + (1-a) * df[field + "_probability_july"]
          # TODO: combine july's uncertainty with mturk variance ??
  
      # Compute beta stuff for july (uncertainty) data
      for field in ["prior", "posterior"]:
          df[field + "_beta_july_certainty_july_probs"] = df.apply(
              lambda x: fit_beta_mean_uncertainty(x[field + "_probability_july"],
                                                  map_certainty_to_variance(x[field + "_certainty_july"])), axis=1)
          df[field + "_beta_july_certainty_mturk_probs"] = df.apply(
              lambda x: fit_beta_mean_uncertainty(x[field + "_mean"],
                                                  map_certainty_to_variance(x[field + "_certainty_july"])), axis=1)
          df[field + "_beta_july_certainty_july_and_mturk_probs"] = df.apply(
              lambda x: fit_beta_mean_uncertainty(x[field + "_mturk_july"],
                                                  map_certainty_to_variance(x[field + "_certainty_july"])), axis=1)
      df["kl_beta_july_certainty_july_probs"] = df.apply(lambda x: kl_dirichlet(x["posterior_beta_july_certainty_july_probs"], x["prior_beta_july_certainty_july_probs"]), axis=1)
      df["kl_beta_july_certainty_mturk_probs"] = df.apply(lambda x: kl_dirichlet(x["posterior_beta_july_certainty_mturk_probs"], x["prior_beta_july_certainty_mturk_probs"]), axis=1)
      df["kl_beta_july_certainty_july_and_mturk_probs"] = df.apply(lambda x: kl_dirichlet(x["posterior_beta_july_certainty_july_and_mturk_probs"], x["prior_beta_july_certainty_july_and_mturk_probs"]), axis=1)
      df["kl_july_and_mturk_probs"] = df.apply(lambda x: kl(x["prior_mturk_july"], x["posterior_mturk_july"]), axis=1)
      df["kl"] = df.apply(lambda x: kl(x["posterior_mean"], x["prior_mean"]), axis=1)
      df["kl_july"] = df.apply(lambda x: kl(x["posterior_probability_july"], x["prior_probability_july"]), axis=1)
      df = df.drop("Notes_july", axis=1)
  
      df.to_json("results_beta.jsonl", orient="records", lines=True)
      df.to_csv("results_beta.csv", index=False)