code: def tie_break(sorted_list, results, prop_key, ndecoys):
      
  
      # Generate a list of the number of decoys that correspond to the FPF
      # values at which enrichment factors were determined, not including ndecoys, the training value
      ndecoys_list = sorted([x for x in list(results.values())[0].ef.keys() if x != ndecoys])
  
      # break the tie the ensemble that maximizes the enrichment factor at a given FPF (that corresponds to ndecoys)
      if prop_key == 'ef':
          index = 0
          while index < len(ndecoys_list) and sorted_list[0][1].get_prop(ndecoys_list[index], prop_key) == \
                  sorted_list[1][1].get_prop(ndecoys_list[index], prop_key):
              sorted_list = sorted(results.items(), key=lambda r: (r[1].get_prop(ndecoys, prop_key),
                                                                   r[1].get_prop(ndecoys_list[index], 'ef')),
                                   reverse=True)
              index += 1
      # break the tie if the ensemble that maximizes the auc is desired
      elif prop_key == 'auc':
          index = 0
          while sorted_list[0][1].get_prop(prop_key) == sorted_list[1][1].get_prop(prop_key) \
                  and index < len(ndecoys_list):
              sorted_list = sorted(results.items(), key = lambda x: (x[1].get_prop(prop_key),
                                                                     x[1].get_prop(ndecoys_list[index])))
              index += 1
  
      return sorted_list
docs: When finding the best ensemble, using "find_best_ensemble," in the event of a tie, we break it by looking at
      enrichment factors at successively larger FPF values, beginning with the smallest FPF not trained on.
      :param sorted_list:
      :param results:
      :return: