import numpy as np

def lddt(predicted_points,
         true_points,
         true_points_mask,
         cutoff=15.,
         per_residue=False):
 """Measure (approximate) lDDT for a batch of coordinates.

 lDDT reference:
 Mariani, V., Biasini, M., Barbato, A. & Schwede, T. lDDT: A local
 superposition-free score for comparing protein structures and models using
 distance difference tests. Bioinformatics 29, 2722-2728 (2013).

 lDDT is a measure of the difference between the true distance matrix and the
 distance matrix of the predicted points. The difference is computed only on
 points closer than cutoff *in the true structure*.

 This function does not compute the exact lDDT value that the original paper
 describes because it does not include terms for physical feasibility
 (e.g. bond length violations). Therefore this is only an approximate
 lDDT score.

 Args:
  predicted_points: (batch, length, 3) array of predicted 3D points
  true_points: (batch, length, 3) array of true 3D points
  true_points_mask: (batch, length, 1) binary-valued float array. This mask
   should be 1 for points that exist in the true points.
  cutoff: Maximum distance for a pair of points to be included
  per_residue: If true, return score for each residue. Note that the overall
   lDDT is not exactly the mean of the per_residue lDDT's because some
   residues have more contacts than others.

 Returns:
  An (approximate, see above) lDDT score in the range 0-1.
 """

  assert len(predicted_points.shape) == 3
  assert predicted_points.shape[-1] == 3
  assert true_points_mask.shape[-1] == 1
  assert len(true_points_mask.shape) == 3

  # Compute true and predicted distance matrices.
  dmat_true = np.sqrt(1e-10 + np.sum((true_points[:, :, None] - true_points[:, None, :])**2, axis=-1))

  dmat_predicted = np.sqrt(1e-10 + np.sum(
  (predicted_points[:, :, None] -
  predicted_points[:, None, :])**2, axis=-1))

  dists_to_score = (
  (dmat_true < cutoff).astype(np.float32) * true_points