code: def acr(tree, df, prediction_method=MPPA, model=F81, column2parameters=None, force_joint=True):
      for c in df.columns:
          df[c] = df[c].apply(lambda _: '' if pd.isna(_) else _.encode('ASCII', 'replace').decode())
      columns = preannotate_tree(df, tree)
      name_tree(tree)
      collapse_zero_branches(tree, features_to_be_merged=df.columns)
      avg_br_len, num_nodes, num_tips = get_tree_stats(tree)
      logging.getLogger('pastml').debug('\n=============ACR===============================')
      column2parameters = column2parameters if column2parameters else {}
      def _work(args):
          return reconstruct_ancestral_states(*args, avg_br_len=avg_br_len, num_nodes=num_nodes, num_tips=num_tips,
                                              force_joint=force_joint)
      prediction_methods = value2list(len(columns), prediction_method, MPPA)
      models = value2list(len(columns), model, F81)
      def get_states(method, model, column):
          df_states = [_ for _ in df[column].unique() if pd.notnull(_) and _ != '']
          if not is_ml(method) or model not in {HKY, JTT}:
              return np.sort(df_states)
          states = HKY_STATES if HKY == model else JTT_STATES
          if not set(df_states) & set(states):
              raise ValueError('The allowed states for model {} are {}, '
                               'but your annotation file specifies {} as states in column {}.'
                               .format(model, ', '.join(states), ', '.join(df_states), column))
          state_set = set(states)
          df[column] = df[column].apply(lambda _: _ if _ in state_set else '')
          return states
      with ThreadPool() as pool:
          acr_results = \
              pool.map(func=_work, iterable=((tree, column, get_states(method, model, column), method, model,
                                              column2parameters[column] if column in column2parameters else None)
                                             for (column, method, model) in zip(columns, prediction_methods, models)))
      result = []
      for acr_res in acr_results:
          if isinstance(acr_res, list):
              result.extend(acr_res)
          else:
              result.append(acr_res)
      return result