AlphaFold3 LDDT(Local Distance Difference Test)计算函数计算局部距离差异测试(Local Distance Difference Test, LDDT) 评分,它是一种用于衡量蛋白质结构预测精度的指标。LDDT 通过比较 预测结构与真实结构之间的局部几何差异,来衡量其精确程度。
LDDT 计算步骤:
- 计算真实和预测结构的原子对距离矩阵
- 筛选出距离在 cutoff(默认 15Å)范围内的原子对
- 计算这些原子对之间的距离差异
- 按照不同阈值(0.5Å、1Å、2Å、4Å)计算匹配度
- 归一化并计算每个残基或整个结构的 LDDT 分数
LDDT 评分比 RMSD 和 GDT 更关注 局部结构的相似性,因此特别适用于衡量蛋白质的局部精度。
源代码:
def lddt(
all_atom_pred_pos: torch.Tensor,
all_atom_positions: torch.Tensor,
all_atom_mask: torch.Tensor,
cutoff: float = 15.0,
eps: float = 1e-10,
per_residue: bool = True,
) -> torch.Tensor:
"""
Compute the local distance difference test (LDDT) score.
Algorithm steps:
1. Compute pairwise distance matrices for true and predicted structures
2. Identify pairs within the cutoff distance
3. Calculate absolute differences between true and predicted distances
4. Score the differences based on predefined thresholds
5. Normalize the scores
Args:
all_atom_pred_pos: Predicted atom positions [..., N, 3]
all_atom_positions: True atom positions [..., N, 3]
all_atom_mask: Mask for valid atoms [..., N]
cutoff: Distance cutoff for considering atom pairs
eps: Small value to avoid division by zero
per_residue: If True, return per-residue scores
Returns:
LDDT scores
"""
# Compute pairwise distance matrices
dmat_true = torch.cdist(all_atom_positions, all_atom_positions)
dmat_pred = torch.cdist(all_atom_pred_pos, all_atom_pred_pos)
# Create mask for pairs within cutoff
dists_to_score = (dmat_true < cutoff).float()
# Apply atom mask
atom_mask_2d = all_atom_mask.unsqueeze(-1) * all_atom_mask.unsqueeze(-2)
dists_to_score = dists_to_score * atom_mask_2d
# Remove self-interactions
eye = torch.eye(dists_to_score.shape[-1], device=dists_to_score.device)
eye = eye.view(*([1] * (dists_to_score.dim() - 2)), *eye.shape)
dists_to_score = dists_to_score * (1 - eye)
# Calculate absolute differences
dist_l1 = torch.abs(dmat_true - dmat_pred)
# Score the differences
score = torch.zeros_like(dist_l1)
for threshold in [0.5, 1.0, 2.0, 4.0]:
score += (dist_l1 < threshold).float()
score *= 0.25 # Normalize by number of thresholds
# Apply scoring mask and sum
scored_pairs = dists_to_score * score
if per_residue:
# Compute per-residue scores
residue_scores = scored_pairs.sum(dim=-1)
residue_weights = dists_to_score.sum(dim=-1)
lddt_score = residue_scores / (residue_weights + eps)
else:
# Compute global score
lddt_score = scored_pairs.sum(dim=(-2, -1)) / (dists_to_score.sum(dim=(-2, -1)) + eps)
return lddt_score
代码解读:
(1) 计算真实和预测结构的两两距离矩阵
dmat_true = torch.cdist(all_atom_positions, all_atom_positions)
dmat_pred = torch.cdist(all_atom_pred_pos, all_atom_pred_pos)
torch.cdist(A, B)
计算两个张量 A 和 B 之间的 欧几里得距离矩阵: