docs: def fraction_correct(x_values, y_values, x_cutoff = 1.0, y_cutoff = 1.0, ignore_null_values = False):
      '''My version of the metric used in the Kellogg et al. paper.
         "Role of conformational sampling in computing mutation-induced changes in protein structure and stability", Proteins, Volume 79, Issue 3, pages 830–838, March 2011.
         http://dx.doi.org/10.1002/prot.22921
         Description: "The fraction correct is defined as the number of mutations categorized correctly divided by the total number of mutations in the benchmark set."
      '''
  
      expected_types, xtypes, ytypes = set([type(None), type(1.0), numpy.float64]), set(map(type, x_values)), set(map(type, x_values))
      assert(not(xtypes.difference(expected_types)) and not(ytypes.difference(expected_types)))
  
      num_points = len(x_values)
      considered_points = num_points
      assert(num_points == len(y_values))
      correct = 0.0
      for i in range(num_points):
          x = x_values[i]
          y = y_values[i]
          if (x == None or y == None or numpy.isnan(x) or numpy.isnan(y)) and ignore_null_values: # If we are missing values then we either discount the case or consider it as incorrect depending on ignore_null_values
              considered_points -= 1
          elif (x >= x_cutoff) and (y >= y_cutoff): # both positive
              correct += 1.0
          elif (x <= -x_cutoff) and (y <= -y_cutoff): # both negative
              correct += 1.0
          elif (-x_cutoff < x < x_cutoff) and (-y_cutoff < y < y_cutoff): # both neutral
              correct += 1.0
      return correct / float(considered_points)