docstr: Calculate ap for every classes
docstr_tok: ["Calculate","ap","for","every","classes"]
code: def cal_ap(self):
      """
      Calculate ap for every classes
      """
      self.ap = [0] * self.num_classes
      self.ap_overlap = [
          [0] * len(self.overlaps) for _ in range(self.num_classes)
      ]
      for i in range(self.num_classes):
          if i not in self.thing_ids:
              continue
          for j in range(len(self.overlaps)):
              y_true = self.y_true[i][j]
              y_score = self.y_score[i][j]
              if len(y_true) == 0:
                  self.ap_overlap[i][j] = 0
                  continue
              score_argsort = np.argsort(y_score)
              y_score_sorted = y_score[score_argsort]
              y_true_sorted = y_true[score_argsort]
              y_true_sorted_cumsum = np.cumsum(y_true_sorted)
  
              # Unique thresholds
              thresholds, unique_indices = np.unique(
                  y_score_sorted, return_index=True
              )
  
              # Since we need to add an artificial point to the precision-recall curve
              # increase its length by 1
              nb_pr = len(unique_indices) + 1
  
              # Calculate precision and recall
              nb_examples = len(y_score_sorted)
              nb_true_exampels = y_true_sorted_cumsum[-1]
              precision = np.zeros(nb_pr)
              recall = np.zeros(nb_pr)
  
              # Deal with the first point
              # only thing we need to do, is to append a zero to the cumsum at the end.
              # An index of -1 uses that zero then
              y_true_sorted_cumsum = np.append(y_true_sorted_cumsum, 0)
  
              # Deal with remaining
              for idx_res, idx_scores in enumerate(unique_indices):
                  cumsum = y_true_sorted_cumsum[idx_scores - 1]
                  tp = nb_true_exampels - cumsum
                  fp = nb_examples - idx_scores - tp
                  fn = cumsum + self.hard_fns[i][j]
                  p = float(tp) / (tp + fp)
                  r = float(tp) / (tp + fn)
                  precision[idx_res] = p
                  recall[idx_res] = r
  
              # Add first point in curve
              precision[-1] = 1.0
              # In some calculation，make precision the max after this point in curve.
              # precision = [np.max(precision[:i+1]) for i in range(len(precision))]
              recall[-1] = 0.0
  
              # Compute average of precision-recall curve
              # integration is performed via zero order, or equivalently step-wise integration
              # first compute the widths of each step:
              # Use a convolution with appropriate kernel, manually deal with the boundaries first
              recall_for_conv = np.copy(recall)
              recall_for_conv = np.append(
                  recall_for_conv[0], recall_for_conv
              )
              recall_for_conv = np.append(recall_for_conv, 0.0)
  
              step_widths = np.convolve(
                  recall_for_conv, [-0.5, 0, 0.5], "valid"
              )
  
              # Integrate is now simply a dot product
              ap_current = np.dot(precision, step_widths)
              self.ap_overlap[i][j] = ap_current
  
      ap = [np.average(i) for i in self.ap_overlap]
      self.ap = ap
  
      return ap
  
file_path: PaddleSeg/contrib/PanopticSeg/paddlepanseg/utils/evaluation/ins_seg_evaluator.py
imports: from collections import defaultdict
  import numpy
  from paddlepanseg.cvlibs import build_info_dict
  from paddlepanseg.utils import decode_pan_id, is_crowd
  from .evaluator import Evaluator
label_desc: Use image node_id 4 for calling the InsSegEvaluator obj's underlying member method code with example usage: obj.cal_ap() and returns: ap