MolecularDiffusion.modules.models.etflow.torchmd¶
TorchMD-ET equivariant transformer, time-conditioned (ET-Flow’s backbone).
Ported near-verbatim from ET-Flow’s etflow/networks/torchmd_net/ (MIT,
(c) 2024 Majdi Hassan, Nikhil Shenoy, Jungyoon Lee), which is itself a fork of
torchmd-net’s TorchMD_ET. Module names and attribute names are load
bearing: they are exactly the ones in the released Zenodo checkpoints
(network.representation_model.* / network.output_model.*), so the
conversion in docs/model_integrations/etflow/scripts/convert_checkpoint.py
is an identity remap and can assert a strict bijection. Renaming anything here
breaks that.
What differs from upstream’s file, and why:
Scalar,EquivariantVectorAndScalarOutput,Distance,GaussianSmearing,ShiftedSoftplusandCoorsNormare dropped. None of them is reachable fromETFlowTask: the output head is fixed toEquivariantVectorOutput,edge_indexis always supplied, and upstream’s own checkpoint schema typesrbf_type/activationasLiteral["expnorm"]/Literal["silu"](commons/configs.py:102,104).norm_coorswas never settable fromBaseFloweither (models/model.py:74-95does not pass it), socoors_normwas alwaysnn.Identity. Dropping them changes nostate_dictkey.The abstract
OutputModelbase is flattened intoEquivariantVectorOutput– it carried no parameters.
Two upstream quirks are kept deliberately, because the published weights were trained with them and “fixing” either would silently invalidate the checkpoints:
edge_weightis the SQUARED interatomic distance, not the distance (r_ijbelow). It is what feeds the RBF expansion and the cosine cutoff.EquivariantVectorOutput.pre_reduceaddsposandTorchMDDynamics.forwardimmediately subtracts it again.
Attributes¶
Classes¶
Smooth 1 -> 0 envelope. Parameter-free. |
|
One time-conditioned equivariant attention block. |
|
Two gated blocks mapping (scalar, vector) features to one 3-vector. |
|
PhysNet-style exponential-normal radial basis. |
|
Gated equivariant block (Schuett et al. 2021), TorchMD-ET variant. |
|
One distance-weighted neighbour aggregation before the transformer. |
|
ET-Flow's vector field: |
|
The stack of time-conditioned equivariant attention blocks. |
Functions¶
|
Subtract each graph's centre of mass. |
Module Contents¶
- class MolecularDiffusion.modules.models.etflow.torchmd.CosineCutoff(cutoff_lower: float = 0.0, cutoff_upper: float = 5.0)¶
Bases:
torch.nn.ModuleSmooth 1 -> 0 envelope. Parameter-free.
- forward(distances: torch.Tensor) torch.Tensor¶
- cutoff_lower = 0.0¶
- cutoff_upper = 5.0¶
- class MolecularDiffusion.modules.models.etflow.torchmd.EquivariantMultiHeadAttention(hidden_channels: int, num_rbf: int, distance_influence: str, num_heads: int, activation, attn_activation: str, cutoff_lower: float, cutoff_upper: float, node_attr_dim: int = 0, qk_norm: bool = False, so3_equivariant: bool = False)¶
Bases:
torch_geometric.nn.MessagePassingOne time-conditioned equivariant attention block.
Time does not get its own embedding: it is concatenated with the node features and the projected
node_attrand mixed bymixing_mlpINSIDE every block (upstreammodel_dynamics.py:116-118).so3_equivariantsplits the value projection into 4 parts instead of 3, adding a cross-product term – SO(3)- rather than O(3)-equivariant, i.e. chirality-aware by construction. False in botho3checkpoints.- aggregate(features, index, ptr, dim_size)¶
- forward(x, vec, edge_index, r_ij, f_ij, d_ij, t, node_attr)¶
- message(q_i, k_j, v_j, vec_j, dk, dv, r_ij, d_ij)¶
- update(inputs)¶
- act¶
- attn_activation¶
- cutoff¶
- distance_influence¶
- dk_proj¶
- dv_proj¶
- head_dim¶
- layernorm¶
- mixing_mlp¶
- node_attr_dim = 0¶
- num_heads¶
- o_proj¶
- qk_norm = False¶
- so3_equivariant = False¶
- v_proj¶
- vec_proj¶
- class MolecularDiffusion.modules.models.etflow.torchmd.EquivariantVectorOutput(hidden_channels: int, activation: str = 'silu', reduce_op: str = 'sum', layer_norm: bool = False)¶
Bases:
torch.nn.ModuleTwo gated blocks mapping (scalar, vector) features to one 3-vector.
- pre_reduce(x, v, z, pos, batch)¶
- output_network¶
- class MolecularDiffusion.modules.models.etflow.torchmd.ExpNormalSmearing(cutoff_lower: float = 0.0, cutoff_upper: float = 5.0, num_rbf: int = 50, trainable: bool = True)¶
Bases:
torch.nn.ModulePhysNet-style exponential-normal radial basis.
trainable=True(upstream’s setting) registersmeans/betasas parameters, which is why they appear in the released checkpoints.- forward(dist: torch.Tensor) torch.Tensor¶
- alpha = 1.0¶
- cutoff_fn¶
- cutoff_lower = 0.0¶
- cutoff_upper = 5.0¶
- num_rbf = 50¶
- trainable = True¶
- class MolecularDiffusion.modules.models.etflow.torchmd.GatedEquivariantBlock(hidden_channels: int, out_channels: int, intermediate_channels: int | None = None, activation: str = 'silu', scalar_activation: bool = False, vector_output: bool = False, layer_norm: bool = True)¶
Bases:
torch.nn.ModuleGated equivariant block (Schuett et al. 2021), TorchMD-ET variant.
- forward(x: torch.Tensor, v: torch.Tensor) tuple[torch.Tensor, torch.Tensor]¶
- act¶
- layer_norm = True¶
- out_channels¶
- update_net¶
- vec1_proj¶
- vec2_proj¶
- vector_output = False¶
- class MolecularDiffusion.modules.models.etflow.torchmd.NeighborEmbedding(hidden_channels: int, num_rbf: int, cutoff_lower: float, cutoff_upper: float, max_z: int = 100)¶
Bases:
torch_geometric.nn.MessagePassingOne distance-weighted neighbour aggregation before the transformer.
- forward(z, x, edge_index, edge_weight, edge_attr)¶
- message(x_j, W)¶
- combine¶
- cutoff¶
- distance_proj¶
- embedding¶
- class MolecularDiffusion.modules.models.etflow.torchmd.TorchMDDynamics(hidden_channels: int = 128, num_layers: int = 8, num_rbf: int = 64, rbf_type: str = 'expnorm', trainable_rbf: bool = False, activation: str = 'silu', neighbor_embedding: bool = True, cutoff_lower: float = 0.0, cutoff_upper: float = 10.0, max_z: int = 100, node_attr_dim: int = 0, edge_attr_dim: int = 0, attn_activation: str = 'silu', num_heads: int = 8, distance_influence: str = 'both', reduce_op: str = 'sum', qk_norm: bool = False, output_layer_norm: bool = True, clip_during_norm: bool = False, so3_equivariant: bool = False)¶
Bases:
torch.nn.ModuleET-Flow’s vector field:
(z, t, pos, edge_index) -> (N, 3).The returned field is centre-of-mass free per graph, which is what makes the flow stay in the zero-COM subspace the harmonic prior lives in.
- forward(z: torch.Tensor, t: torch.Tensor, pos: torch.Tensor, edge_index: torch.Tensor, batch: torch.Tensor, edge_attr: torch.Tensor | None = None, node_attr: torch.Tensor | None = None) torch.Tensor¶
Args mirror upstream’s;
tarrives already broadcast per atom.
- output_model¶
- representation_model¶
- class MolecularDiffusion.modules.models.etflow.torchmd.TorchMD_ET_dynamics(hidden_channels: int = 128, num_layers: int = 6, num_rbf: int = 50, rbf_type: str = 'expnorm', trainable_rbf: bool = True, activation: str = 'silu', attn_activation: str = 'silu', neighbor_embedding: bool = True, num_heads: int = 8, distance_influence: str = 'both', cutoff_lower: float = 0.0, cutoff_upper: float = 10.0, max_z: int = 100, node_attr_dim: int = 0, edge_attr_dim: int = 0, qk_norm: bool = False, clip_during_norm: bool = False, so3_equivariant: bool = False)¶
Bases:
torch.nn.ModuleThe stack of time-conditioned equivariant attention blocks.
- forward(z: torch.Tensor, t: torch.Tensor, pos: torch.Tensor, batch: torch.Tensor, edge_index: torch.Tensor | None = None, node_attr: torch.Tensor | None = None, edge_attr: torch.Tensor | None = None)¶
- activation = 'silu'¶
- attention_layers¶
- attn_activation = 'silu'¶
- clip_during_norm = False¶
- cutoff_lower = 0.0¶
- cutoff_upper = 10.0¶
- distance_expansion¶
- distance_influence = 'both'¶
- edge_attr_dim = 0¶
- embedding¶
- max_z = 100¶
- neighbor_embedding¶
- node_attr_dim = 0¶
- num_heads = 8¶
- num_layers = 6¶
- num_rbf = 50¶
- out_norm¶
- rbf_type = 'expnorm'¶
- trainable_rbf = True¶
- MolecularDiffusion.modules.models.etflow.torchmd.center(pos: torch.Tensor, batch: torch.Tensor) torch.Tensor¶
Subtract each graph’s centre of mass.
- MolecularDiffusion.modules.models.etflow.torchmd.act_class_mapping¶