code: def _analyse_results(
      res_file,
      ann_file,
      res_types,
      out_dir=None,
      extraplots=None,
      areas=None,
      max_detections=500,
      COCO=None,
      COCOeval=None,
  ):
      for res_type in res_types:
          if res_type not in ["bbox", "segm"]:
              raise ValueError(f"res_type {res_type} is not supported")
      if areas is not None:
          if len(areas) != 3:
              raise ValueError(
                  "3 integers should be specified as areas,representing 3 area regions"
              )
  
      if out_dir is None:
          out_dir = Path(res_file).parent
          out_dir = str(out_dir / "coco_error_analysis")
  
      directory = os.path.dirname(out_dir + "/")
      if not os.path.exists(directory):
          print(f"-------------create {out_dir}-----------------")
          os.makedirs(directory)
  
      result_type_to_export_paths = {}
  
      cocoGt = COCO(ann_file)
      cocoDt = cocoGt.loadRes(res_file)
      imgIds = cocoGt.getImgIds()
      for res_type in res_types:
          res_out_dir = out_dir + "/" + res_type + "/"
          res_directory = os.path.dirname(res_out_dir)
          if not os.path.exists(res_directory):
              print(
                  f"-------------create {res_out_dir}-----------------"
              )
              os.makedirs(res_directory)
          iou_type = res_type
          cocoEval = COCOeval(
              copy.deepcopy(cocoGt), copy.deepcopy(cocoDt), iou_type
          )
          cocoEval.params.imgIds = imgIds
          cocoEval.params.iouThrs = [0.75, 0.5, 0.1]
          cocoEval.params.maxDets = [max_detections]
          if areas is not None:
              cocoEval.params.areaRng = [
                  [0**2, areas[2]],
                  [0**2, areas[0]],
                  [areas[0], areas[1]],
                  [areas[1], areas[2]],
              ]
          cocoEval.evaluate()
          cocoEval.accumulate()
  
          present_cat_ids = []
          catIds = cocoGt.getCatIds()
          for k, catId in enumerate(catIds):
              image_ids = cocoGt.getImgIds(catIds=[catId])
              if len(image_ids) != 0:
                  present_cat_ids.append(catId)
          matrix_shape = list(cocoEval.eval["precision"].shape)
          matrix_shape[2] = len(present_cat_ids)
          ps = np.zeros(matrix_shape)
  
          for k, catId in enumerate(present_cat_ids):
              ps[:, :, k, :, :] = cocoEval.eval["precision"][
                  :, :, catId, :, :
              ]
          ps = np.vstack([ps, np.zeros((4, *ps.shape[1:]))])
  
          recThrs = cocoEval.params.recThrs
          with Pool(processes=48) as pool:
              args = [
                  (
                      k,
                      cocoDt,
                      cocoGt,
                      catId,
                      iou_type,
                      areas,
                      max_detections,
                      COCOeval,
                  )
                  for k, catId in enumerate(present_cat_ids)
              ]
              analyze_results = pool.starmap(
                  _analyze_individual_category, args
              )
  
          classname_to_export_path_list = {}
          for k, catId in enumerate(present_cat_ids):
              nm = cocoGt.loadCats(catId)[0]
              print(
                  f'--------------saving {k + 1}-{nm["name"]}---------------'
              )
              analyze_result = analyze_results[k]
              if k != analyze_result[0]:
                  raise ValueError(
                      f"k {k} != analyze_result[0] {analyze_result[0]}"
                  )
              ps_supercategory = analyze_result[1]["ps_supercategory"]
              ps_allcategory = analyze_result[1]["ps_allcategory"]
              # compute precision but ignore superclass confusion
              ps[3, :, k, :, :] = ps_supercategory
              # compute precision but ignore any class confusion
              ps[4, :, k, :, :] = ps_allcategory
              # fill in background and false negative errors and plot
              ps[5, :, k, :, :][ps[4, :, k, :, :] == -1] = -1
              ps[5, :, k, :, :][ps[4, :, k, :, :] > 0] = 1
              ps[6, :, k, :, :] = 1.0
  
              normalized_class_name = (
                  nm["name"].replace("/", "_").replace(os.sep, "_")
              )
  
              curve_export_path_list = _makeplot(
                  recThrs,
                  ps[:, :, k],
                  res_out_dir,
                  normalized_class_name,
                  iou_type,
              )
  
              if extraplots:
                  bar_plot_path = _makebarplot(
                      recThrs,
                      ps[:, :, k],
                      res_out_dir,
                      normalized_class_name,
                      iou_type,
                  )
              else:
                  bar_plot_path = None
              classname_to_export_path_list[nm["name"]] = {
                  "curves": curve_export_path_list,
                  "bar_plot": bar_plot_path,
              }
  
          curve_export_path_list = _makeplot(
              recThrs, ps, res_out_dir, "allclass", iou_type
          )
          if extraplots:
              bar_plot_path = _makebarplot(
                  recThrs, ps, res_out_dir, "allclass", iou_type
              )
              gt_area_group_numbers_plot_path = (
                  _make_gt_area_group_numbers_plot(
                      cocoEval=cocoEval,
                      outDir=res_out_dir,
                      verbose=True,
                  )
              )
              gt_area_histogram_plot_path = (
                  _make_gt_area_histogram_plot(
                      cocoEval=cocoEval, outDir=res_out_dir
                  )
              )
          else:
              (
                  bar_plot_path,
                  gt_area_group_numbers_plot_path,
                  gt_area_histogram_plot_path,
              ) = (None, None, None)
  
          result_type_to_export_paths[res_type] = {
              "classwise": classname_to_export_path_list,
              "overall": {
                  "bar_plot": bar_plot_path,
                  "curves": curve_export_path_list,
                  "gt_area_group_numbers": gt_area_group_numbers_plot_path,
                  "gt_area_histogram": gt_area_histogram_plot_path,
              },
          }
      print(
          f"COCO error analysis results are successfully exported to {out_dir}"
      )
  
      return result_type_to_export_paths
  
file_path: sahi/sahi/scripts/coco_error_analysis.py
imports: import copy
  import os
  from multiprocessing import Pool
  from pathlib import Path
  from typing import List
  import fire
  import numpy
label_desc: Use image node_id 8 for calling a global function with example usage: _analyse_results(res_file, ann_file, res_types, out_dir, extraplots, areas, max_detections, COCO, COCOeval) and returns: result_type_to_export_paths