Structure module, templates and recycling · INTEGRATION
Normalized-quaternion backbone updates
AlphaFold2OpenFoldESMFoldRFdiffusion
Free account with email, Google or GitHub. Your code runs in an isolated PyTorch sandbox.
Your task
Update residue frames and place their local points in world coordinates. The selected mode determines whether the increment is expressed in the residue’s local frame or in the global frame; this changes both rotation composition and translation. Preserve each immovable frame and return the normalized quaternion increment.
Function signature
quaternion_frame_update(
rotation: torch.Tensor,
translation: torch.Tensor,
local_points: torch.Tensor,
movable: torch.Tensor,
options: dict,
single: torch.Tensor | None = None,
w_update: torch.Tensor | None = None,
b_update: torch.Tensor | None = None,
offsets: torch.Tensor | None = None,
) -> dict[str, torch.Tensor]Worked example
Global and local rotation order differ
At the frame-update stage, take one movable residue whose old rotation is a positive quarter-turn about z and whose old translation is zero. Suppose the supplied or projected increments, after the declared scales, are u=(1,0,0) and v=(1,0,0). Quaternion (1,1,0,0)/sqrt(2) gives Rx, a positive quarter-turn about x. RFdiffusion global mode uses R_new=Rx·Rz and new translation (1,0,0). Local point (0,1,0) becomes (-1,0,0) under Rz, stays there under Rx, and ends at (0,0,0) after translation. For the same scaled increments, AF2 local mode instead gives (0,1,1) because it uses Rz·Rx and rotates v with the old Rz.
Parameters
| Parameter | Shape and meaning |
|---|---|
rotationtorch.Tensor | [B, N, 3, 3]Proper rotation mapping local vectors into world coordinates. |
translationtorch.Tensor | [B, N, 3]World origin of each frame. |
local_pointstorch.Tensor | [B, N, P, 3]Points expressed in each frame’s local coordinates. |
movabletorch.Tensor | [B, N]\mathrm{True}=\mathrm{update} allowed |
singletorch.Tensor | NoneDefault None | [B, N, C]Learned scalar representation used only by the AF2 update projection. |
w_updatetorch.Tensor | NoneDefault None | [C, 6]af2_local: [C,6] learned backbone-update head |
b_updatetorch.Tensor | NoneDefault None | [6]Supplied update affine offset; add it only at its named projection or normalization stage. |
offsetstorch.Tensor | NoneDefault None | [B, N, 2, 3]Supplied global translation offset in slot 0 and rotation-vector offset in slot 1. |
optionsdict | Scalar settings. Omitted keys use the defaults below. |
Return
dict[str, torch.Tensor]
Return exactly the named fields applicable to this operation.
Required behavior
- Update each supplied proper
rotation[B,N,3,3],translation[B,N,3] and transformlocal_points[B,N,P,3] with column-vector convention.B,N,Pand feature widthCare positive; all floats finite.movable[B,N]Truepermits an increment; protected residues still return their existing transformedpoints. mode='af2_local'(default): compute\mathrm{update}=\mathrm{single}[B,N,C]@w_{\mathrm{update}}[C,6]+b_{\mathrm{update}}[6]. First3 channels arerotationvectoru, final3translationvectorv. Default\mathrm{rotation\_scale}=\mathrm{translation\_scale}=1.mode='rfdiffusion_global': takeoffsets[B,N,2,3] from the separately learned SE(3) network; slot0 istranslationv, slot1rotationu. Default\mathrm{translation\_scale}=0.1and\mathrm{rotation\_scale}=0.01, following original RFdiffusion's /10and /100.scalesare finite nonnegative numbers.- In either mode multiply
u/vby these scales and zero both wheremovable=False. Form a WXYZ quaternionq=(1,u)/\sqrt{1+\sum(u^{2})}; no\epsilonis necessary. Convertqto the proper activerotationdelta_R. af2_localapplies\mathrm{rotation\_new}=\mathrm{rotation}\mathbin{@}\delta_{R}and\mathrm{translation\_new}=\mathrm{translation}+\mathrm{rotation}\mathbin{@}v, wheretranslationuses the OLDrotation.rfdiffusion_globalapplies\mathrm{rotation\_new}=\delta_{R}\mathbin{@}\mathrm{rotation}and\mathrm{translation\_new}=\mathrm{translation}+v; do not rotate the oldtranslation.- Return
\mathrm{points}=\mathrm{rotation\_new}\mathbin{@}\mathrm{local\_points}+\mathrm{translation\_new}anddelta_quaternion[B,N,4] as well as the new transform. Zero increment gives the identity update; a protected residue has\delta_{\mathrm{quaternion}}=(1,0,0,0). - No detach, stochastic integrator, axis-angle exponential, or post-update quaternion sign-flip convention is included. Original RFdiffusion's
motif_mask=Truemeans protected; the suppliedmovablemask intentionally has the opposite polarity.
Why this matters
The same rotation increment can act in the residue’s local coordinates or in the global frame. The selected mode determines both the multiplication order and how the translation increment is interpreted.
Starter code
You write the body of this function in the BioTorch workspace. Your code runs in an isolated PyTorch sandbox; Run checks the public examples and Submit grades the full test suite, including gradients.
import torch
def quaternion_frame_update(
rotation: torch.Tensor, # (B, N, 3, 3)
translation: torch.Tensor, # (B, N, 3)
local_points: torch.Tensor, # (B, N, P, 3)
movable: torch.Tensor, # (B, N)
options: dict,
single: torch.Tensor | None = None, # (B, N, C)
w_update: torch.Tensor | None = None, # (C, 6)
b_update: torch.Tensor | None = None, # (6)
offsets: torch.Tensor | None = None, # (B, N, 2, 3)
) -> dict[str, torch.Tensor]:
"""Return dict[str, torch.Tensor]:
rotation: (B, N, 3, 3).
translation: (B, N, 3).
points: (B, N, P, 3).
delta_quaternion: (B, N, 4)."""
# Implement the operation. Inputs and test setup are supplied by BioTorch.
raise NotImplementedError("Implement quaternion_frame_update")
Ready to implement it?
3 progressive hints, a solution walkthrough, and grading that checks values, shapes and gradients are waiting in the workspace.
Free account with email, Google or GitHub. Your code runs in an isolated PyTorch sandbox.
Related exercises
Sources and further reading
A primitive exercise, not an end-to-end reproduction of the named models. No affiliation or endorsement is implied.