code: def compute_rand_index(test_labels, ground_truth_labels, mask):
      """Calculate the Rand Index
  
      http://en.wikipedia.org/wiki/Rand_index
  
      Given a set of N elements and two partitions of that set, X and Y
  
      A = the number of pairs of elements in S that are in the same set in
          X and in the same set in Y
      B = the number of pairs of elements in S that are in different sets
          in X and different sets in Y
      C = the number of pairs of elements in S that are in the same set in
          X and different sets in Y
      D = the number of pairs of elements in S that are in different sets
          in X and the same set in Y
  
      The rand index is:   A + B
                              -----
                          A+B+C+D
  
  
      The adjusted rand index is the rand index adjusted for chance
      so as not to penalize situations with many segmentations.
  
      Jorge M. Santos, Mark Embrechts, "On the Use of the Adjusted Rand
      Index as a Metric for Evaluating Supervised Classification",
      Lecture Notes in Computer Science,
      Springer, Vol. 5769, pp. 175-184, 2009. Eqn # 6
  
      ExpectedIndex = best possible score
  
      ExpectedIndex = sum(N_i choose 2) * sum(N_j choose 2)
  
      MaxIndex = worst possible score = 1/2 (sum(N_i choose 2) + sum(N_j choose 2)) * total
  
      A * total - ExpectedIndex
      -------------------------
      MaxIndex - ExpectedIndex
  
      returns a tuple of the Rand Index and the adjusted Rand Index
      """
      ground_truth_labels = ground_truth_labels[mask].astype(np.uint32)
      test_labels = test_labels[mask].astype(np.uint32)
      if len(test_labels) > 0:
          #
          # Create a sparse matrix of the pixel labels in each of the sets
          #
          # The matrix, N(i,j) gives the counts of all of the pixels that were
          # labeled with label I in the ground truth and label J in the
          # test set.
          #
          N_ij = scipy.sparse.coo_matrix(
              (
                  np.ones(len(test_labels)),
                  (ground_truth_labels, test_labels),
              )
          ).toarray()
  
          def choose2(x):
              """Compute # of pairs of x things = x * (x-1) / 2"""
              return x * (x - 1) / 2
  
          #
          # Each cell in the matrix is a count of a grouping of pixels whose
          # pixel pairs are in the same set in both groups. The number of
          # pixel pairs is n * (n - 1), so A = sum(matrix * (matrix - 1))
          #
          A = np.sum(choose2(N_ij))
          #
          # B is the sum of pixels that were classified differently by both
          # sets. But the easier calculation is to find A, C and D and get
          # B by subtracting A, C and D from the N * (N - 1), the total
          # number of pairs.
          #
          # For C, we take the number of pixels classified as "i" and for each
          # "j", subtract N(i,j) from N(i) to get the number of pixels in
          # N(i,j) that are in some other set = (N(i) - N(i,j)) * N(i,j)
          #
          # We do the similar calculation for D
          #
          N_i = np.sum(N_ij, 1)
          N_j = np.sum(N_ij, 0)
          C = np.sum((N_i[:, np.newaxis] - N_ij) * N_ij) / 2
          D = np.sum((N_j[np.newaxis, :] - N_ij) * N_ij) / 2
          total = choose2(len(test_labels))
          # an astute observer would say, why bother computing A and B
          # when all we need is A+B and C, D and the total can be used to do
          # that. The calculations aren't too expensive, though, so I do them.
          B = total - A - C - D
          rand_index = (A + B) / total
          #
          # Compute adjusted Rand Index
          #
          expected_index = np.sum(choose2(N_i)) * np.sum(choose2(N_j))
          max_index = (
              (np.sum(choose2(N_i)) + np.sum(choose2(N_j))) * total / 2
          )
  
          adjusted_rand_index = (A * total - expected_index) / (
              max_index - expected_index
          )
      else:
          rand_index = adjusted_rand_index = np.nan
      return rand_index, adjusted_rand_index
  
imports: import numpy
  import scipy
  import centrosome
  import centrosome.cpmorphology
  import centrosome.filter
  import centrosome.propagate
  import centrosome.fastemd
  from sklearn.cluster import KMeans
  from cellprofiler_library.opts import measureimageoverlap
  from cellprofiler_library.functions.segmentation import convert_labels_to_ijv
  from cellprofiler_library.functions.segmentation import indices_from_ijv
  from cellprofiler_library.functions.segmentation import count_from_ijv
  from cellprofiler_library.functions.segmentation import areas_from_ijv
  from cellprofiler_library.functions.segmentation import cast_labels_to_label_set
label_desc: Use image node_id 2 for calling a global function with example usage: compute_rand_index(test_labels, ground_truth_labels, mask) and returns: rand_index,  adjusted_rand_index, unknown