def _gather_valid_indices(tensor, indices, padding_value=0.0):
  """Gather values for valid indices.

  TODO(rathodv): We can't use ops.gather_with_padding_values due to cyclic
  dependency. Start using it after migrating all users of spatial ops to import
  this module directly rather than util/ops.py

  Args:
    tensor: A tensor to gather valid values from.
    indices: A 1-D int32 tensor containing indices along axis 0 of `tensor`.
      Invalid indices must be marked with -1.
    padding_value: Value to return for invalid indices.

  Returns:
    A tensor sliced based on indices. For indices that are equal to -1, returns
    rows of padding value.
  """
  padded_tensor = tf.concat(
      [
          padding_value *
          tf.ones([1, tf.shape(tensor)[-1]], dtype=tensor.dtype), tensor
      ],
      axis=0,
  )
  # tf.concat gradient op uses tf.where(condition) (which is not
  # supported on TPU) when the inputs to it are tf.IndexedSlices instead of
  # tf.Tensor. Since gradient op for tf.gather returns tf.IndexedSlices,
  # we add a dummy op inbetween tf.concat and tf.gather to ensure tf.concat
  # gradient function gets tf.Tensor inputs and not tf.IndexedSlices.
  padded_tensor *= 1.0
  return tf.gather(padded_tensor, indices + 1)
Gather values for valid indices.

  TODO(rathodv): We can't use ops.gather_with_padding_values due to cyclic
  dependency. Start using it after migrating all users of spatial ops to import
  this module directly rather than util/ops.py

  Args:
    tensor: A tensor to gather valid values from.
    indices: A 1-D int32 tensor containing indices along axis 0 of `tensor`.
      Invalid indices must be marked with -1.
    padding_value: Value to return for invalid indices.

  Returns:
    A tensor sliced based on indices. For indices that are equal to -1, returns
    rows of padding value.
  
inference_api/src/main/object_detection/utils/spatial_transform_ops.py