code: def _compute_pr_curves(samples, config, classes=None):
      gt_field = config.gt_field
      pred_field = config.pred_field
      iou_threshs = config.iou_threshs
  
      samples = samples.select_fields([gt_field, pred_field])
  
      gt_field, processing_frames = samples._handle_frame_field(
          gt_field
      )
      pred_field, _ = samples._handle_frame_field(pred_field)
  
      num_threshs = len(iou_threshs)
      thresh_matches = [{} for _ in range(num_threshs)]
  
      if classes is None:
          _classes = set()
  
      logger.info("Performing IoU sweep...")
      for sample in samples.iter_samples(progress=True):
          if processing_frames:
              images = sample.frames.values()
          else:
              images = [sample]
  
          for image in images:
              # Don't edit user's data during sweep
              gts = _copy_labels(image[gt_field])
              preds = _copy_labels(image[pred_field])
  
              matches_list = _coco_evaluation_iou_sweep(
                  gts, preds, config
              )
  
              for idx, matches in enumerate(matches_list):
                  for match in matches:
                      gt_label = match[0]
                      pred_label = match[1]
                      iscrowd = match[-1]
  
                      if classes is None:
                          _classes.add(gt_label)
                          _classes.add(pred_label)
  
                      if iscrowd:
                          continue
  
                      c = (
                          gt_label
                          if gt_label is not None
                          else pred_label
                      )
  
                      if c not in thresh_matches[idx]:
                          thresh_matches[idx][c] = {
                              "tp": [],
                              "fp": [],
                              "num_gt": 0,
                          }
  
                      if gt_label == pred_label:
                          thresh_matches[idx][c]["tp"].append(match)
                      elif pred_label:
                          thresh_matches[idx][c]["fp"].append(match)
  
                      if gt_label:
                          thresh_matches[idx][c]["num_gt"] += 1
  
      if classes is None:
          _classes.discard(None)
          classes = sorted(_classes)
  
      num_classes = len(classes)
      class_idx_map = {c: idx for idx, c in enumerate(classes)}
  
      # Compute precision-recall
      # https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocotools/cocoeval.py
      precision = -np.ones((num_threshs, num_classes, 101))
      thresholds = -np.ones((num_threshs, num_classes, 101))
      recall = np.linspace(0, 1, 101)
      for idx, _thresh_matches in enumerate(thresh_matches):
          for c, matches in _thresh_matches.items():
              c_idx = class_idx_map.get(c, None)
              num_gt = matches["num_gt"]
  
              if c_idx is None or num_gt == 0:
                  continue
  
              tp = matches["tp"]
              fp = matches["fp"]
              tp_fp = np.array([1] * len(tp) + [0] * len(fp))
              confs = np.array([m[3] for m in tp] + [m[3] for m in fp])
              if None in confs:
                  raise ValueError(
                      "All predicted objects must have their `confidence` "
                      "attribute populated in order to compute precision-recall "
                      "curves"
                  )
  
              inds = np.argsort(-confs, kind="mergesort")
              tp_fp = tp_fp[inds]
              confs = confs[inds]
  
              tp_sum = np.cumsum(tp_fp).astype(dtype=float)
              total = np.arange(1, len(tp_fp) + 1).astype(dtype=float)
  
              pre = tp_sum / total
              rec = tp_sum / num_gt
  
              for i in range(len(pre) - 1, 0, -1):
                  if pre[i] > pre[i - 1]:
                      pre[i - 1] = pre[i]
  
              q = np.zeros(101)
              t = np.zeros(101)
  
              inds = np.searchsorted(rec, recall, side="left")
  
              try:
                  for ri, pi in enumerate(inds):
                      q[ri] = pre[pi]
                      t[ri] = confs[pi]
              except:
                  pass
  
              precision[idx][c_idx] = q
              thresholds[idx][c_idx] = t
  
      return precision, recall, thresholds, iou_threshs, classes
  
imports: import logging
  from collections import defaultdict
  import numpy
  import eta.core.utils
  import fiftyone.core.plots
  import fiftyone.utils.iou
  from .detection import DetectionEvaluation, DetectionEvaluationConfig, DetectionResults
label_desc: Use image node_id 5 for calling a global function with example usage: _compute_pr_curves(samples, config, classes) and returns: precision,  recall,  thresholds,  iou_threshs,  classes