code: def compute_ng_stat(gene_graph, pos_ct, alpha=.5):
      
      # skip if there are no missense mutations
      if not len(pos_ct):
          return 1.0, 0
  
      max_pos = max(gene_graph)
      codon_vals = np.zeros(max_pos+1)
  
      # smooth out mutation counts
      for pos in pos_ct:
          mut_count = pos_ct[pos]
  
          # update neighbor values
          neighbors = list(gene_graph[pos])
          num_neighbors = len(neighbors)
          codon_vals[neighbors] += alpha*mut_count
  
          # update self-value
          codon_vals[pos] += (1-alpha)*mut_count
  
      # compute the normalized entropy
      #total_cts = float(np.count_nonzero(codon_vals))
      #graph_score = mymath.normalized_mutation_entropy(codon_vals, total_cts=total_cts)
  
      # compute regular entropy
      p = codon_vals / np.sum(codon_vals)
      graph_score = mymath.shannon_entropy(p)
  
      # get coverage
      coverage = np.count_nonzero(p)
  
      return graph_score, coverage
docs: Compute the clustering score for the gene on its neighbor graph.
  
      Parameters
      ----------
      gene_graph : dict
          Graph of spatially near codons. keys = nodes, edges = key -> value.
      pos_ct : dict
          missense mutation count for each codon
      alpha : float
          smoothing factor
  
      Returns
      -------
      graph_score : float
          score measuring the clustering of missense mutations in the graph
      coverage : int
          number of nodes that received non-zero weight