code: def tempo_evaluation(detections, annotations, tolerance=TOLERANCE):
      """
      Calculate the tempo P-Score, at least one and all tempi correct.
  
      Parameters
      ----------
      detections : list of tuples or numpy array
          Detected tempi (rows, first column) and their relative strengths
          (second column).
      annotations : list or numpy array
          Annotated tempi (rows, first column) and their relative strengths
          (second column).
      tolerance : float, optional
          Evaluation tolerance (max. allowed deviation).
  
      Returns
      -------
      pscore : float
          P-Score.
      at_least_one : bool
          At least one tempo correctly identified.
      all : bool
          All tempi correctly identified.
  
      Notes
      -----
      All given detections are evaluated against all annotations according to the
      relative strengths given. If no strengths are given, evenly distributed
      strengths are assumed. If the strengths do not sum to 1, they will be
      normalized.
  
      References
      ----------
      .. [1] M. McKinney, D. Moelants, M. Davies and A. Klapuri,
             "Evaluation of audio beat tracking and music tempo extraction
             algorithms",
             Journal of New Music Research, vol. 36, no. 1, 2007.
  
      """
      # neither detections nor annotations are given
      if len(detections) == 0 and len(annotations) == 0:
          # perfect result
          return 1.0, True, True
      # either detections or annotations are empty
      if len(detections) == 0 or len(annotations) == 0:
          # worst result
          return 0.0, False, False
      # tolerance must be greater than 0
      if float(tolerance) <= 0:
          raise ValueError("tolerance must be greater than 0")
      # make sure the annotations and detections have a float dtype
      detections = np.array(detections, dtype=float, ndmin=1)
      annotations = np.array(annotations, dtype=float, ndmin=1)
      # extract the detected tempi, ignore the strengths
      if detections.ndim == 2:
          detections = detections[:, 0]
      # extract the annotated tempi and strengths
      strengths = []
      if annotations.ndim == 2:
          # Note: extract the strength before using only the tempo annotations
          strengths = annotations[:, 1]
          annotations = annotations[:, 0]
      # strengths must sum up to 1
      strengths_sum = np.sum(strengths)
      if strengths_sum == 0:
          # uniformly distribute strengths
          warnings.warn(
              "no annotated tempo strengths given, assuming a uniform "
              "distribution"
          )
          strengths = np.ones_like(annotations) / float(
              len(annotations)
          )
      elif strengths_sum != 1:
          # normalize strengths
          warnings.warn(
              "annotated tempo strengths do not sum to 1, normalizing"
          )
          strengths /= float(strengths_sum)
      # test all detected tempi against all annotated tempi
      errors = np.abs(1 - (detections[:, np.newaxis] / annotations))
      # correctly identified annotation tempi
      correct = np.asarray(np.sum(errors <= tolerance, axis=0), bool)
      # the P-Score is the sum of the strengths of the correctly identified tempi
      pscore = np.sum(strengths[correct])
      # return the scores
      # TODO: also return the errors?
      return pscore, correct.any(), correct.all()
  
imports: from __future__ import absolute_import, division, print_function
  import warnings
  import numpy
  from .None import EvaluationMixin, MeanEvaluation, evaluation_io
  from ..io import load_tempo
label_desc: Use image node_id 2 for calling a global function with example usage: tempo_evaluation(detections, annotations, tolerance) and returns: pscore,  correct,  correct, int,  True,  True, int,  False,  False