code: def onset_evaluation(detections, annotations, window=WINDOW):
      """
      Determine the true/false positive/negative detections.
  
      Parameters
      ----------
      detections : numpy array
          Detected notes.
      annotations : numpy array
          Annotated ground truth notes.
      window : float, optional
          Evaluation window [seconds].
  
      Returns
      -------
      tp : numpy array, shape (num_tp,)
          True positive detections.
      fp : numpy array, shape (num_fp,)
          False positive detections.
      tn : numpy array, shape (0,)
          True negative detections (empty, see notes).
      fn : numpy array, shape (num_fn,)
          False negative detections.
      errors : numpy array, shape (num_tp,)
          Errors of the true positive detections wrt. the annotations.
  
      Notes
      -----
      The returned true negative array is empty, because we are not interested
      in this class, since it is magnitudes bigger than true positives array.
  
      """
      # make sure the arrays have the correct types and dimensions
      detections = np.asarray(detections, dtype=float)
      annotations = np.asarray(annotations, dtype=float)
      # TODO: right now, it only works with 1D arrays
      if detections.ndim > 1 or annotations.ndim > 1:
          raise NotImplementedError(
              "please implement multi-dim support"
          )
  
      # init TP, FP, FN and errors
      tp = np.zeros(0)
      fp = np.zeros(0)
      tn = np.zeros(0)  # we will not alter this array
      fn = np.zeros(0)
      errors = np.zeros(0)
  
      # if neither detections nor annotations are given
      if len(detections) == 0 and len(annotations) == 0:
          # return the arrays as is
          return tp, fp, tn, fn, errors
      # if only detections are given
      elif len(annotations) == 0:
          # all detections are FP
          return tp, detections, tn, fn, errors
      # if only annotations are given
      elif len(detections) == 0:
          # all annotations are FN
          return tp, fp, tn, annotations, errors
  
      # window must be greater than 0
      if float(window) <= 0:
          raise ValueError("window must be greater than 0")
  
      # sort the detections and annotations
      det = np.sort(detections)
      ann = np.sort(annotations)
      # cache variables
      det_length = len(detections)
      ann_length = len(annotations)
      det_index = 0
      ann_index = 0
      # iterate over all detections and annotations
      while det_index < det_length and ann_index < ann_length:
          # fetch the first detection
          d = det[det_index]
          # fetch the first annotation
          a = ann[ann_index]
          # compare them
          if abs(d - a) <= window:
              # TP detection
              tp = np.append(tp, d)
              # append the error to the array
              errors = np.append(errors, d - a)
              # increase the detection and annotation index
              det_index += 1
              ann_index += 1
          elif d < a:
              # FP detection
              fp = np.append(fp, d)
              # increase the detection index
              det_index += 1
              # do not increase the annotation index
          elif d > a:
              # we missed a annotation: FN
              fn = np.append(fn, a)
              # do not increase the detection index
              # increase the annotation index
              ann_index += 1
          else:
              # can't match detected with annotated onset
              raise AssertionError("can not match % with %", d, a)
      # the remaining detections are FP
      fp = np.append(fp, det[det_index:])
      # the remaining annotations are FN
      fn = np.append(fn, ann[ann_index:])
      # check calculations
      if len(tp) + len(fp) != len(detections):
          raise AssertionError("bad TP / FP calculation")
      if len(tp) + len(fn) != len(annotations):
          raise AssertionError("bad FN calculation")
      if len(tp) != len(errors):
          raise AssertionError("bad errors calculation")
      # convert to numpy arrays and return them
      return (
          np.array(tp),
          np.array(fp),
          tn,
          np.array(fn),
          np.array(errors),
      )
  
imports: from __future__ import absolute_import, division, print_function
  import numpy
  from .None import Evaluation, MeanEvaluation, SumEvaluation, evaluation_io
  from ..io import load_onsets
  from ..utils import combine_events
label_desc: Use image node_id 1 for calling a global function with example usage: onset_evaluation(detections, annotations, window) and returns: np,  np,  tn,  np,  np, tp,  fp,  tn,  fn,  errors, tp,  detections,  tn,  fn,  errors, tp,  fp,  tn,  annotations,  errors