code: def eval_det_cls(
      pred,
      gt,
      ovthresh=0.25,
      use_07_metric=False,
      get_iou_func=box3d_iou,
      classname="",
  ):
      """Generic functions to compute precision/recall for object detection
      for a single class.
      Args:
          pred: map of {img_id: [(bbox, score)]} where bbox is numpy array
          gt: map of {img_id: [bbox]}
          ovthresh: scalar, iou threshold
          use_07_metric: bool, if True use VOC07 11 point method
          get_iou_func: function handle for get_iou_func(box1, box2)
          classname: int
  
      Returns:
          rec: numpy array of length nd
          prec: numpy array of length nd
          ap: scalar, average precision
          confidence: numpy array, used to find precision and recall in offline processing given specific conf_threshold
      """
      tt = time.time()
  
      msg = "compute pr for single class of {}".format(classname)
      print(msg)
  
      class_recs = (
          {}
      )  # {img_id: {'bbox': bbox list, 'det': matched list}}
      npos = 0
      for img_id in gt.keys():
          bbox = np.array(gt[img_id])
          det = [False] * len(bbox)
          npos += len(
              bbox
          )  # total number of gt boxes. This is max number of possible correct predictions
          class_recs[img_id] = {"bbox": bbox, "det": det}
      # pad empty list to all other imgids
  
      for img_id in pred.keys():
          if img_id not in gt:
              class_recs[img_id] = {"bbox": np.array([]), "det": []}
  
      # construct dets
      image_ids = []
      confidence = []
      BB = []
      for img_id in pred.keys():
          for box, score in pred[img_id]:
              image_ids.append(img_id)
              confidence.append(score)
              BB.append(box)
      confidence = np.array(confidence)
      BB = np.array(BB)  # (nd,4 or 8,3 or 6)
  
      # sort by confidence
      sorted_ind = np.argsort(-confidence)
      sorted_scores = np.sort(-confidence)
      BB = BB[sorted_ind, ...]
      image_ids = [image_ids[x] for x in sorted_ind]
  
      # go down dets and mark TPs and FPs
      # num of predicted box instances. say 100 boxes, and their img_ids (may contain a lot of duplicates, just appended)
      nd = len(image_ids)
      tp = np.zeros(nd)
      fp = np.zeros(nd)
      for d in range(nd):  # global all img_ids
          R = class_recs[image_ids[d]]
          bb = BB[d, ...].astype(float)
          ovmax = -np.inf
          BBGT = R["bbox"].astype(float)
  
          if BBGT.size > 0:
              # compute overlaps
              for j in range(BBGT.shape[0]):
                  iou = get_iou_func(bb, BBGT[j, ...])
                  if iou > ovmax:
                      ovmax = iou
                      jmax = j
  
          # check where 0.05 box confidence is used, for such low thr, fn is our hard examples to collect
          # if high threshold like 0.9, (fp is hard negative) we would be collecting hard FPs, this is because when we
          # set a high conf_threshold of 0.9, only those predicted boxes with very high confidence gets to be evaluated
          # so they are very likely to be TPs, in such scenario, if there is still FP, this means we encounter a hard FP
          # or hard negative example
  
          # confidence threshold changed from 0.05 to 0.9 to get false negatives
          # text file: 14 X 2 numbers of text files
          # for each category, we have a FP list, and a FN list
          # for each table list, we have full file path of 34578274_box_78.npy / npz, space, number of FPs,
          # for each table list, ... FNs
  
          if ovmax > ovthresh:
              if not R["det"][jmax]:
                  tp[d] = 1.0
                  R["det"][jmax] = 1
              else:
                  # even though the IoU is more than IoU threshold, but there is already a box earlier with higher
                  # confidence that marked this gt box as having a TP detection, as ft[d] set to 1
                  # img_id, no. of fp += 1
                  fp[d] = 1.0
                  # save_num_of_fp_per_img_id(classname, image_ids[d])
          else:
              # no gt box has IoU more than threshold
              fp[d] = 1.0
              # img_id, no. of fp += 1
              # save_num_of_fp_per_img_id(classname, image_ids[d])
  
      # compute precision recall
      tp_per_instance = tp.copy()
      fp = np.cumsum(fp)
      tp = np.cumsum(tp)
      rec = tp / float(npos + 1e-4)
      # avoid divide by zero in case the first detection matches a difficult
      # ground truth
      prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)
      ap = voc_ap(rec, prec, use_07_metric)
  
      msg = "----------------------- time for evaluating model: {} seconds".format(
          int(time.time() - tt)
      )
      print(msg)
  
      return rec, prec, ap
  
file_path: ARKitScenes/threedod/benchmark_scripts/utils/eval_utils.py
imports: import numpy
  import time
  from .box_utils import box3d_iou
label_desc: Use image node_id 1 for calling a global function with example usage: eval_det_cls(pred, gt, ovthresh, use_07_metric, get_iou_func, classname) and returns: rec,  prec,  ap