class_docstr: ActivityNet-style evaluation.
  
  Args:
      config: a :class:`ActivityNetEvaluationConfig`
class_docstr_tok: ["ActivityNet-style","evaluation",".","Args",":","config",":","a",":","class",":","`","ActivityNetEvaluationConfig","`"]
docstr: Generates aggregate evaluation results for the samples.
  
  If ``self.config.compute_mAP`` is True, this method performs
  ActivityNet-style evaluation as in :meth:`evaluate` to generate
  precision and recall sweeps over the range of IoU thresholds in
  ``self.config.iou_threshs``. In this case, an
  :class:`ActivityNetDetectionResults` instance is returned that can
  compute mAP and PR curves.
  
  Args:
      samples: a :class:`fiftyone.core.collections.SampleCollection`
      matches: a list of
          ``(gt_label, pred_label, iou, pred_confidence, gt_id, pred_id)``
          matches. Either label can be ``None`` to indicate an unmatched
          segment
      eval_key (None): the evaluation key for this evaluation
      classes (None): the list of possible classes. If not provided, the
          observed ground truth/predicted labels are used for results
          purposes
      missing (None): a missing label string. Any unmatched segments are
          given this label for results purposes
  
  Returns:
      a :class:`DetectionResults`
docstr_tok: ["Generates","aggregate","evaluation","results","for","the","samples",".","If","``","self.config.compute_mAP","``","is","True",",","this","method","performs","ActivityNet-style","evaluation","as","in",":","meth",":","`","evaluate","`","to","generate","precision","and","recall","sweeps","over","the","range","of","IoU","thresholds","in","``","self.config.iou_threshs","``",".","In","this","case",",","an",":","class",":","`","ActivityNetDetectionResults","`","instance","is","returned","that","can","compute","mAP","and","PR","curves",".","Args",":","samples",":","a",":","class",":","`","fiftyone.core.collections.SampleCollection","`","matches",":","a","list","of","``","(","gt_label",",","pred_label",",","iou",",","pred_confidence",",","gt_id",",","pred_id",")","``","matches",".","Either","label","can","be","``","None","``","to","indicate","an","unmatched","segment","eval_key","(","None",")",":","the","evaluation","key","for","this","evaluation","classes","(","None",")",":","the","list","of","possible","classes",".","If","not","provided",",","the","observed","ground","truth\/predicted","labels","are","used","for","results","purposes","missing","(","None",")",":","a","missing","label","string",".","Any","unmatched","segments","are","given","this","label","for","results","purposes","Returns",":","a",":","class",":","`","DetectionResults","`"]
code: def generate_results(
      self, samples, matches, eval_key=None, classes=None, missing=None
  ):
      """Generates aggregate evaluation results for the samples.
  
      If ``self.config.compute_mAP`` is True, this method performs
      ActivityNet-style evaluation as in :meth:`evaluate` to generate
      precision and recall sweeps over the range of IoU thresholds in
      ``self.config.iou_threshs``. In this case, an
      :class:`ActivityNetDetectionResults` instance is returned that can
      compute mAP and PR curves.
  
      Args:
          samples: a :class:`fiftyone.core.collections.SampleCollection`
          matches: a list of
              ``(gt_label, pred_label, iou, pred_confidence, gt_id, pred_id)``
              matches. Either label can be ``None`` to indicate an unmatched
              segment
          eval_key (None): the evaluation key for this evaluation
          classes (None): the list of possible classes. If not provided, the
              observed ground truth/predicted labels are used for results
              purposes
          missing (None): a missing label string. Any unmatched segments are
              given this label for results purposes
  
      Returns:
          a :class:`DetectionResults`
      """
      if not self.config.compute_mAP:
          return DetectionResults(
              samples,
              self.config,
              eval_key,
              matches,
              classes=classes,
              missing=missing,
              backend=self,
          )
  
      gt_field = self.config.gt_field
      pred_field = self.config.pred_field
  
      _samples = samples.select_fields([gt_field, pred_field])
  
      iou_threshs = self.config.iou_threshs
      thresh_matches = {t: {} for t in iou_threshs}
  
      if classes is None:
          _classes = set()
      else:
          _classes = None
  
      # IoU sweep
      logger.info("Performing IoU sweep...")
      for sample in _samples.iter_samples(progress=True):
          # Don't edit user's data during sweep
          gts = _copy_labels(sample[self.gt_field])
          preds = _copy_labels(sample[self.pred_field])
  
          video_matches = _activitynet_evaluation_iou_sweep(
              gts, preds, self.config
          )
  
          for t, t_matches in video_matches.items():
              for match in t_matches:
                  gt_label = match[0]
                  pred_label = match[1]
  
                  if _classes is not None:
                      _classes.add(gt_label)
                      _classes.add(pred_label)
  
                  c = gt_label if gt_label is not None else pred_label
  
                  if c not in thresh_matches[t]:
                      thresh_matches[t][c] = {
                          "tp": [],
                          "fp": [],
                          "num_gt": 0,
                      }
  
                  if gt_label == pred_label:
                      thresh_matches[t][c]["tp"].append(match)
                  elif pred_label:
                      thresh_matches[t][c]["fp"].append(match)
  
                  if gt_label:
                      thresh_matches[t][c]["num_gt"] += 1
  
      if _classes is not None:
          _classes.discard(None)
          classes = sorted(_classes)
  
      # Compute precision-recall array
      # https://github.com/activitynet/ActivityNet/blob/master/Evaluation/eval_detection.py
      num_threshs = len(iou_threshs)
      num_classes = len(classes)
      precision = -np.ones((num_threshs, num_classes, 101))
      thresholds = -np.ones((num_threshs, num_classes, 101))
      classwise_AP = -np.ones((num_threshs, num_classes))
      recall = np.linspace(0, 1, 101)
      for t in thresh_matches.keys():
          for c in thresh_matches[t].keys():
              tp = thresh_matches[t][c]["tp"]
              fp = thresh_matches[t][c]["fp"]
              num_gt = thresh_matches[t][c]["num_gt"]
              if num_gt == 0:
                  continue
  
              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 segments 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]
  
              # ActivityNet mAP is calculated without interpolated precision
              # This slightly differs from COCO evaluation
              mprec = np.hstack([[0], pre, [0]])
              mrec = np.hstack([[0], rec, [1]])
              idx = np.where(mrec[1::] != mrec[0:-1])[0] + 1
              ap = np.sum((mrec[idx] - mrec[idx - 1]) * mprec[idx])
  
              q = np.zeros(101)
              tr = np.zeros(101)
  
              # Interpolate precision values for PR curve plotting purposes
              inds = np.searchsorted(rec, recall, side="left")
              try:
                  for ri, pi in enumerate(inds):
                      q[ri] = pre[pi]
                      tr[ri] = confs[pi]
              except:
                  pass
  
              precision[iou_threshs.index(t)][classes.index(c)] = q
              thresholds[iou_threshs.index(t)][classes.index(c)] = tr
              classwise_AP[iou_threshs.index(t)][classes.index(c)] = ap
  
      return ActivityNetDetectionResults(
          samples,
          self.config,
          eval_key,
          matches,
          precision,
          recall,
          classwise_AP,
          iou_threshs,
          classes,
          thresholds=thresholds,
          missing=missing,
          backend=self,
      )
  
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 3 for calling the ActivityNetEvaluation obj's underlying member method code with example usage: obj.generate_results(samples, matches, eval_key, classes, missing) and returns: ActivityNetDetectionResults, DetectionResults