code: def normalize_log10_probs(log10_probs):
      """Approximately normalizes log10 probabilities.
  
      This function normalizes log10 probabilities. What this means is that we
      return an equivalent array of probabilities but whereas sum(10^log10_probs) is
      not necessarily 1.0, the resulting array is sum(10^result) ~= 1.0. The ~=
      indicates that the result is not necessarily == 1.0 but very close.
  
      This function is a fast and robust approximation of the true normalization of
      a log10 transformed probability vector. To understand the approximation,
      let's start with the exact calculation. Suppose I have three models, each
      emitting a probability that some data was generated by that model:
  
        data = {0.1, 0.01, 0.001} => probabilities from models A, B, and C
  
      These probabilities are unnormalized, in the sense that the total probability
      over the vector doesn't sum to 1 (sum(data) = 0.111). In many applications we
      want to normalize this vector so that sum(normalized(data)) = 1 and the
      relative magnitudes of the original probabilities are preserved (i.e,:
  
        data[i] / data[j] = normalized(data)[i] / normalized(data)[j]
  
      for all pairs of values indexed by i and j. For much of the work we do in
      genomics, we have so much data that representing these raw probability
      vectors in real-space risks numeric underflow/overflow, so we instead
      represent our probability vectors in log10 space:
  
        log10_data = log10(data) = {-1, -2, -3}
  
      Given that we expect numeric problems in real-space, normalizing this log10
      vector is hard, because the standard way you'd do the normalization is via:
  
        data[i] = data[i] / sum(data)
        log10_data[i] = log10_data[i] - log10(sum(10^data))
  
      But computing the sum of log10 values this way is dangerous because the naive
      implementation converts back to real-space to do the sum, the very operation
      we're trying to avoid due to numeric instability.
  
      This function implements an approximate normalization, which relaxes the need
      for an exact calculation of the sum. This function ensures that the
      normalization is numerically safe at the expense of the sum not being exactly
      equal to 1 but rather just close.
  
      Args:
        log10_probs: array-like of floats. An array of log10 probabilties.
  
      Returns:
        np.array with the same shape as log10_probs but where sum(10^result) ~= 1.0.
  
      Raises:
        ValueError: if any log10_probs > 0.0
      """
      log10_probs = np.array(log10_probs)
      if np.max(log10_probs) > 0.0:
          raise ValueError("log10_probs all must be <= 0", log10_probs)
      lse = log10sumexp(log10_probs)
      # np.minimum protects us from producing values slightly > 0.0 (e.g., 1e-16).
      return np.minimum(log10_probs - lse, 0.0)
  
file_path: deepvariant/third_party/nucleus/util/genomics_math.py
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import math
  import numpy
  from third_party.nucleus.util.python import math
label_desc: Use image node_id 5 for calling a global function with example usage: normalize_log10_probs(log10_probs) and returns: np