code: def information_gain(
      detections, annotations, num_bins=INFORMATION_GAIN_BINS
  ):
      """
      Calculate information gain for the given detections and annotations.
  
      Parameters
      ----------
      detections : list or numpy array
          Detected beats.
      annotations : list or numpy array
          Annotated beats.
      num_bins : int, optional
          Number of bins for the beat error histogram.
  
      Returns
      -------
      information_gain : float
          Information gain.
      error_histogram : numpy array
          Error histogram.
  
      References
      ----------
      .. [1] M. E.P. Davies, N. Degara and M. D. Plumbley,
             "Measuring the performance of beat tracking algorithms algorithms
             using a beat error histogram",
             IEEE Signal Processing Letters, vol. 18, vo. 3, 2011.
  
      """
      # neither detections nor annotations are given, perfect score
      if len(detections) == 0 and len(annotations) == 0:
          # return a max. information gain and an empty error histogram
          return np.log2(num_bins), np.zeros(num_bins)
      # either beat detections or annotations are empty, score 0
      # Note: use "or" here since we test both the detections against the
      #       annotations and vice versa during the evaluation process
      if len(detections) <= 1 or len(annotations) <= 1:
          # return an information gain of 0 and a uniform beat error histogram
          # Note: because swapped detections and annotations should return the
          #       same uniform histogram, the maximum length of the detections
          #       and annotations is chosen (instead of just the length of the
          #       annotations as in the Matlab implementation).
          max_length = max(len(detections), len(annotations))
          return 0.0, np.ones(num_bins) * max_length / float(num_bins)
      # at least 2 annotations must be given to calculate an interval
      if len(detections) < 2 or len(annotations) < 2:
          raise BeatIntervalError(
              "At least 2 annotations and 2 detections are"
              "needed for Information gain."
          )
      # check if there are enough beat annotations for the number of bins
      if num_bins > len(annotations):
          warnings.warn(
              "Not enough beat annotations (%d) for %d histogram bins."
              % (len(annotations), num_bins)
          )
      # create bins edges for the error histogram
      histogram_bins = _histogram_bins(num_bins)
      # evaluate detections against annotations
      fwd_histogram = _error_histogram(
          detections, annotations, histogram_bins
      )
      fwd_ig = _information_gain(fwd_histogram)
      # if only a few (but correct) beats are detected, the errors could be small
      # thus evaluate also the annotations against the detections, i.e. simulate
      # a lot of false positive detections
      bwd_histogram = _error_histogram(
          annotations, detections, histogram_bins
      )
      bwd_ig = _information_gain(bwd_histogram)
      # only use the lower information gain
      if fwd_ig < bwd_ig:
          return fwd_ig, fwd_histogram
      return bwd_ig, bwd_histogram
  
imports: from __future__ import absolute_import, division, print_function
  import warnings
  from functools import wraps
  import numpy
  from .None import MeanEvaluation, calc_absolute_errors, calc_errors, evaluation_io, find_closest_matches
  from .onsets import OnsetEvaluation
label_desc: Use image node_id 17 for calling a global function with example usage: information_gain(detections, annotations, num_bins) and returns: bwd_ig,  bwd_histogram, np,  np, int,  unknown, fwd_ig,  fwd_histogram