code: def candidate_generation(
      self,
      max_rank=None,
      save_gold_pos=False,
      save_pregenerated_gold_pos=False,
  ):
      has_gold_per_dataset = {}
      total_per_dataset = {}
      recall = {}
      processed_mentions = self.data
  
      if max_rank is None:
          print("Max rank: None")
      else:
          print("Max rank", max_rank)
  
      for mention in processed_mentions:
          dataset_name = mention["dataset_name"]
          gold_wikidata_id = mention["gold_wikidata_id"]
          gold_pos = -1
  
          for idx, cand in enumerate(mention["generated_candidates"]):
              cand_wikidata_id = cand["wikidata_id"]
              if gold_wikidata_id == cand_wikidata_id:
                  gold_pos = idx + 1  # Because idx starts at 0
                  break
  
          if save_gold_pos:
              mention["gold_pos"] = gold_pos
  
          if gold_pos > 0 and (
              (max_rank is None) or gold_pos <= max_rank
          ):
              has_gold = has_gold_per_dataset.get(dataset_name, 0) + 1
              has_gold_per_dataset[dataset_name] = has_gold
  
          if save_pregenerated_gold_pos:
              pre_gen_gold_pos = -1
  
              for idx, cand in enumerate(mention["candidates_data"]):
                  cand_wikidata_id = cand["wikidata_id"]
                  if gold_wikidata_id == cand_wikidata_id:
                      pre_gen_gold_pos = (
                          idx + 1
                      )  # Because idx starts at 0
                      break
  
              mention["pre_gen_candidates_gold_pos"] = pre_gen_gold_pos
  
          total = total_per_dataset.get(dataset_name, 0) + 1
          total_per_dataset[dataset_name] = total
  
      total = 0
      has_gold = 0
  
      for dataset_name in total_per_dataset:
          has_gold_ds = has_gold_per_dataset.get(dataset_name, 0)
          total_ds = total_per_dataset[dataset_name]
  
          has_gold += has_gold_ds
          total += total_ds
  
          recall[dataset_name] = has_gold_ds / total_ds
          print("Dataset:", dataset_name)
          print(
              "Recall (w.r.t candidate generation): {:.3f}".format(
                  recall[dataset_name]
              )
          )
  
      recall["overall"] = has_gold / total
      print(
          "Overal recall (w.r.t candidate generation): {:.3f}".format(
              recall["overall"]
          )
      )
  
      self.has_gold_per_dataset = has_gold_per_dataset
      self.total_per_dataset = total_per_dataset
      self.total = total
      self.has_gold = has_gold
      self.recall = recall
  
imports: import matplotlib.pyplot
  import numpy
  from collections import Counter
label_desc: Use image node_id 2 for calling the Evaluator obj's underlying member method code with example usage: obj.candidate_generation(max_rank, save_gold_pos, save_pregenerated_gold_pos) without return types