code: def _calculate_ap_per_class(
      labels: List[Dict[str, Any]],
      predictions: List[np.ndarray],
      *,
      iou_threshold: Optional[float] = 0.5,
      num_procs: int = 1,
  ) -> List:
      """
      Computes the average precision for each class based on provided labels and predictions.
      It uses an Intersection over Union (IoU) threshold and supports parallel processing with a specified number of processes.
  
      """
      num_images = len(predictions)
      num_scale = 1
      num_classes = len(predictions[0])
      if num_images > 1:
          num_procs = min(num_procs, num_images)
          pool = Pool(num_procs)
      ap_per_class_list = []
      for class_num in range(num_classes):
          pred_bboxes, lab_bboxes = _filter_by_class(
              labels, predictions, class_num
          )
          if num_images > 1:
              tpfp = pool.starmap(
                  _calculate_true_positives_false_positives,
                  zip(
                      pred_bboxes,
                      lab_bboxes,
                      [iou_threshold for _ in range(num_images)],
                  ),
              )
          else:
              tpfp = [
                  _calculate_true_positives_false_positives(
                      pred_bboxes[0],
                      lab_bboxes[0],
                      iou_threshold,
                  )
              ]
          true_positives, false_positives = tuple(zip(*tpfp))
          num_gts = np.zeros(num_scale, dtype=int)
          for j, bbox in enumerate(lab_bboxes):
              num_gts[0] += bbox.shape[0]
          pred_bboxes = np.vstack(pred_bboxes)
          sort_inds = np.argsort(-pred_bboxes[:, -1])
          true_positives = np.hstack(true_positives)[:, sort_inds]
          false_positives = np.hstack(false_positives)[:, sort_inds]
          true_positives = np.cumsum(true_positives, axis=1)
          false_positives = np.cumsum(false_positives, axis=1)
          eps = np.finfo(np.float32).eps
          recalls = true_positives / np.maximum(
              num_gts[:, np.newaxis], eps
          )
          precisions = true_positives / np.maximum(
              (true_positives + false_positives), eps
          )
          recalls = recalls[0, :]
          precisions = precisions[0, :]
          ap = _calculate_average_precision(recalls, precisions)
          ap_per_class_list.append(ap)
      if num_images > 1:
          pool.close()
      return ap_per_class_list
  
file_path: cleanlab/cleanlab/object_detection/filter.py
imports: from collections import defaultdict
  from multiprocessing import Pool
  from typing import Any, Dict, List, Optional, Tuple, Union
  import numpy
  from cleanlab.internal.constants import ALPHA, HIGH_PROBABILITY_THRESHOLD, LOW_PROBABILITY_THRESHOLD, OVERLOOKED_THRESHOLD_FACTOR, BADLOC_THRESHOLD_FACTOR, SWAP_THRESHOLD_FACTOR, AP_SCALE_FACTOR
  from cleanlab.internal.object_detection_utils import assert_valid_inputs
  from cleanlab.object_detection.rank import _get_valid_inputs_for_compute_scores, _separate_label, _separate_prediction, compute_badloc_box_scores, compute_overlooked_box_scores, compute_swap_box_scores, get_label_quality_scores, issues_from_scores, _get_overlap_matrix
label_desc: Use image node_id 6 for calling a global function with example usage: _calculate_ap_per_class(labels, predictions) and returns: ap_per_class_list