docstr: Compute statistics needed for COCO metrics (mAP, AP of individual classes, mAP@IoU_Thresholds, AR)
  Adapted from https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocotools/cocoeval.py
  
  Args:
      results_list (list[dict[int, dict[str, np.ndarray]]]): list with result s per image (in list)
          per category (dict). Inner dict contains multiple results obtained by :func:`box_matching_batch`.
  
          - `dtMatches`: matched detections [T, D], where T = number of
            thresholds, D = number of detections
          - `gtMatches`: matched ground truth boxes [T, G], where T = number
            of thresholds, G = number of ground truth
          - `dtScores`: prediction scores [D] detection scores
          - `gtIgnore`: ground truth boxes which should be ignored
            [G] indicate whether ground truth should be ignored
          - `dtIgnore`: detections which should be ignored [T, D],
            indicate which detections should be ignored
  
  Returns:
      dict: computed statistics over dataset
          - `counts`: Number of thresholds, Number recall thresholds, Number of classes, Number of max
            detection thresholds
          - `recall`: Computed recall values [num_iou_th, num_classes, num_max_detections]
          - `precision`: Precision values at specified recall thresholds
            [num_iou_th, num_recall_th, num_classes, num_max_detections]
          - `scores`: Scores corresponding to specified recall thresholds
            [num_iou_th, num_recall_th, num_classes, num_max_detections]
docstr_tok: ["Compute","statistics","needed","for","COCO","metrics","(","mAP",",","AP","of","individual","classes",",","mAP","@","IoU_Thresholds",",","AR",")","Adapted","from","https",":","\/\/github.com\/cocodataset\/cocoapi\/blob\/master\/PythonAPI\/pycocotools\/cocoeval.py","Args",":","results_list","(","list","[","dict","[","int",",","dict","[","str",",","np.ndarray","]","]","]",")",":","list","with","result","s","per","image","(","in","list",")","per","category","(","dict",")",".","Inner","dict","contains","multiple","results","obtained","by",":","func",":","`","box_matching_batch","`",".","-","`","dtMatches","`",":","matched","detections","[","T",",","D","]",",","where","T","=","number","of","thresholds",",","D","=","number","of","detections","-","`","gtMatches","`",":","matched","ground","truth","boxes","[","T",",","G","]",",","where","T","=","number","of","thresholds",",","G","=","number","of","ground","truth","-","`","dtScores","`",":","prediction","scores","[","D","]","detection","scores","-","`","gtIgnore","`",":","ground","truth","boxes","which","should","be","ignored","[","G","]","indicate","whether","ground","truth","should","be","ignored","-","`","dtIgnore","`",":","detections","which","should","be","ignored","[","T",",","D","]",",","indicate","which","detections","should","be","ignored","Returns",":","dict",":","computed","statistics","over","dataset","-","`","counts","`",":","Number","of","thresholds",",","Number","recall","thresholds",",","Number","of","classes",",","Number","of","max","detection","thresholds","-","`","recall","`",":","Computed","recall","values","[","num_iou_th",",","num_classes",",","num_max_detections","]","-","`","precision","`",":","Precision","values","at","specified","recall","thresholds","[","num_iou_th",",","num_recall_th",",","num_classes",",","num_max_detections","]","-","`","scores","`",":","Scores","corresponding","to","specified","recall","thresholds","[","num_iou_th",",","num_recall_th",",","num_classes",",","num_max_detections","]"]
code: def _compute_statistics(
      self, results_list: list[dict[int, dict[str, np.ndarray]]]
  ) -> dict[str, np.ndarray | list]:
      """
      Compute statistics needed for COCO metrics (mAP, AP of individual classes, mAP@IoU_Thresholds, AR)
      Adapted from https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocotools/cocoeval.py
  
      Args:
          results_list (list[dict[int, dict[str, np.ndarray]]]): list with result s per image (in list)
              per category (dict). Inner dict contains multiple results obtained by :func:`box_matching_batch`.
  
              - `dtMatches`: matched detections [T, D], where T = number of
                thresholds, D = number of detections
              - `gtMatches`: matched ground truth boxes [T, G], where T = number
                of thresholds, G = number of ground truth
              - `dtScores`: prediction scores [D] detection scores
              - `gtIgnore`: ground truth boxes which should be ignored
                [G] indicate whether ground truth should be ignored
              - `dtIgnore`: detections which should be ignored [T, D],
                indicate which detections should be ignored
  
      Returns:
          dict: computed statistics over dataset
              - `counts`: Number of thresholds, Number recall thresholds, Number of classes, Number of max
                detection thresholds
              - `recall`: Computed recall values [num_iou_th, num_classes, num_max_detections]
              - `precision`: Precision values at specified recall thresholds
                [num_iou_th, num_recall_th, num_classes, num_max_detections]
              - `scores`: Scores corresponding to specified recall thresholds
                [num_iou_th, num_recall_th, num_classes, num_max_detections]
      """
      num_iou_th = len(self.iou_thresholds)
      num_recall_th = len(self.recall_thresholds)
      num_classes = len(self.classes)
      num_max_detections = len(self.max_detections)
  
      # -1 for the precision of absent categories
      precision = -np.ones(
          (num_iou_th, num_recall_th, num_classes, num_max_detections)
      )
      recall = -np.ones((num_iou_th, num_classes, num_max_detections))
      scores = -np.ones(
          (num_iou_th, num_recall_th, num_classes, num_max_detections)
      )
  
      for cls_idx, cls_i in enumerate(self.classes):  # for each class
          for max_det_idx, max_det in enumerate(
              self.max_detections
          ):  # for each maximum number of detections
              results = [
                  r[cls_idx] for r in results_list if cls_idx in r
              ]  # len is num_images
  
              if len(results) == 0:
                  logger.warning(
                      f"WARNING, no results found for coco metric for class {cls_i}"
                  )
                  continue
  
              dt_scores = np.concatenate(
                  [r["dtScores"][0:max_det] for r in results]
              )
              # different sorting method generates slightly different results.
              # mergesort is used to be consistent as Matlab implementation.
              inds = np.argsort(-dt_scores, kind="mergesort")
              dt_scores_sorted = dt_scores[inds]
  
              # r['dtMatches'] [T, R], where R = sum(all detections)
              dt_matches = np.concatenate(
                  [r["dtMatches"][:, 0:max_det] for r in results],
                  axis=1,
              )[:, inds]
              dt_ignores = np.concatenate(
                  [r["dtIgnore"][:, 0:max_det] for r in results], axis=1
              )[:, inds]
              self.check_number_of_iou(dt_matches, dt_ignores)
              gt_ignore = np.concatenate(
                  [r["gtIgnore"] for r in results]
              )
              num_gt = np.count_nonzero(
                  gt_ignore == 0
              )  # number of ground truth boxes (non ignored)
              if num_gt == 0:
                  logger.warning(
                      f"WARNING, no gt found for coco metric for class {cls_i}"
                  )
                  continue
  
              # ignore cases need to be handled differently for tp and fp
              tps = np.logical_and(
                  dt_matches, np.logical_not(dt_ignores)
              )
              fps = np.logical_and(
                  np.logical_not(dt_matches), np.logical_not(dt_ignores)
              )
  
              tp_sum = np.cumsum(tps, axis=1).astype(dtype=np.float32)
              fp_sum = np.cumsum(fps, axis=1).astype(dtype=np.float32)
  
              for th_ind, (tp, fp) in enumerate(
                  zip(tp_sum, fp_sum)
              ):  # for each threshold th_ind
                  tp, fp = np.array(tp), np.array(fp)
                  r, p, s = _compute_stats_single_threshold(
                      tp,
                      fp,
                      dt_scores_sorted,
                      self.recall_thresholds,
                      num_gt,
                  )
                  recall[th_ind, cls_idx, max_det_idx] = r
                  precision[th_ind, :, cls_idx, max_det_idx] = p
                  # corresponding score thresholds for recall steps
                  scores[th_ind, :, cls_idx, max_det_idx] = s
  
      return {
          "counts": [
              num_iou_th,
              num_recall_th,
              num_classes,
              num_max_detections,
          ],  # [4]
          "recall": recall,  # [num_iou_th, num_classes, num_max_detections]
          "precision": precision,  # [num_iou_th, num_recall_th, num_classes, num_max_detections]
          "scores": scores,  # [num_iou_th, num_recall_th, num_classes, num_max_detections]
      }
  
file_path: MONAI/monai/apps/detection/metrics/coco.py
imports: from __future__ import annotations
  import logging
  import time
  from collections.abc import Sequence
  from typing import Any
  import numpy
label_desc: Use image node_id 10 for calling the COCOMetric obj's underlying member method code with example usage: obj._compute_statistics(results_list) and returns: dict