docs: def evaluate_box_proposals(
      predictions, dataset, thresholds=None, area="all", limit=None
  ):
      """Evaluate detection proposal recall metrics. This function is a much
      faster alternative to the official COCO API recall evaluation code. However,
      it produces slightly different results.
      """
      # Record max overlap value for each gt box
      # Return vector of overlap values
      areas = {
          "all": 0,
          "small": 1,
          "medium": 2,
          "large": 3,
          "96-128": 4,
          "128-256": 5,
          "256-512": 6,
          "512-inf": 7,
      }
      area_ranges = [
          [0 ** 2, 1e5 ** 2],  # all
          [0 ** 2, 32 ** 2],  # small
          [32 ** 2, 96 ** 2],  # medium
          [96 ** 2, 1e5 ** 2],  # large
          [96 ** 2, 128 ** 2],  # 96-128
          [128 ** 2, 256 ** 2],  # 128-256
          [256 ** 2, 512 ** 2],  # 256-512
          [512 ** 2, 1e5 ** 2],
      ]  # 512-inf
      assert area in areas, "Unknown area range: {}".format(area)
      area_range = area_ranges[areas[area]]
      gt_overlaps = []
      num_pos = 0
  
      for image_id, prediction in enumerate(predictions):
          original_id = dataset.id_to_img_map[image_id]
  
          img_info = dataset.get_img_info(image_id)
          image_width = img_info["width"]
          image_height = img_info["height"]
          prediction = prediction.resize((image_width, image_height))
  
          # sort predictions in descending order
          # TODO maybe remove this and make it explicit in the documentation
          inds = prediction.get_field("objectness").sort(descending=True)[1]
          prediction = prediction[inds]
  
          ann_ids = dataset.coco.getAnnIds(imgIds=original_id)
          anno = dataset.coco.loadAnns(ann_ids)
          gt_boxes = [obj["bbox"] for obj in anno if obj["iscrowd"] == 0]
          gt_boxes = torch.as_tensor(gt_boxes).reshape(-1, 4)  # guard against no boxes
          gt_boxes = BoxList(gt_boxes, (image_width, image_height), mode="xywh").convert(
              "xyxy"
          )
          gt_areas = torch.as_tensor([obj["area"] for obj in anno if obj["iscrowd"] == 0])
  
          if len(gt_boxes) == 0:
              continue
  
          valid_gt_inds = (gt_areas >= area_range[0]) & (gt_areas <= area_range[1])
          gt_boxes = gt_boxes[valid_gt_inds]
  
          num_pos += len(gt_boxes)
  
          if len(gt_boxes) == 0:
              continue
  
          if len(prediction) == 0:
              continue
  
          if limit is not None and len(prediction) > limit:
              prediction = prediction[:limit]
  
          overlaps = boxlist_iou(prediction, gt_boxes)
  
          _gt_overlaps = torch.zeros(len(gt_boxes))
          for j in range(min(len(prediction), len(gt_boxes))):
              # find which proposal box maximally covers each gt box
              # and get the iou amount of coverage for each gt box
              max_overlaps, argmax_overlaps = overlaps.max(dim=0)
  
              # find which gt box is 'best' covered (i.e. 'best' = most iou)
              gt_ovr, gt_ind = max_overlaps.max(dim=0)
              assert gt_ovr >= 0
              # find the proposal box that covers the best covered gt box
              box_ind = argmax_overlaps[gt_ind]
              # record the iou coverage of this gt box
              _gt_overlaps[j] = overlaps[box_ind, gt_ind]
              assert _gt_overlaps[j] == gt_ovr
              # mark the proposal box and the gt box as used
              overlaps[box_ind, :] = -1
              overlaps[:, gt_ind] = -1
  
          # append recorded iou coverage level
          gt_overlaps.append(_gt_overlaps)
      gt_overlaps = torch.cat(gt_overlaps, dim=0)
      gt_overlaps, _ = torch.sort(gt_overlaps)
  
      if thresholds is None:
          step = 0.05
          thresholds = torch.arange(0.5, 0.95 + 1e-5, step, dtype=torch.float32)
      recalls = torch.zeros_like(thresholds)
      # compute recall for each iou threshold
      for i, t in enumerate(thresholds):
          recalls[i] = (gt_overlaps >= t).float().sum() / float(num_pos)
      # ar = 2 * np.trapz(recalls, thresholds)
      ar = recalls.mean()
      return {
          "ar": ar,
          "recalls": recalls,
          "thresholds": thresholds,
          "gt_overlaps": gt_overlaps,
          "num_pos": num_pos,
      }