MolecularDiffusion.modules.models.diffsbdd.en_diffusion¶
DiffSBDD’s E(3)-equivariant DDPMs over a ligand + protein-pocket system.
Ported from equivariant_diffusion/en_diffusion.py and
equivariant_diffusion/conditional_model.py. Two selectable models:
EnVariationalDiffusion(mode: joint) – diffuses ligand and pocket together. Itsinpaint()is also how upstream does pocket-conditioned generation in joint mode (lightning_modules.py:814-834): a zero ligand withlig_fixed=0andpocket_fixed=1. De-novo generation and fragment-fixing are the same call with a differentlig_fixed.ConditionalDDPM(mode: pocket_conditioning) – diffuses the ligand only; the pocket is clean, never-noised context, and the system is kept translation-invariant by re-centring on the ligand CoM each step. It has bothsample_given_pocket()and its owninpaint().
Continuous Gaussian noise on coordinates and the one-hot feature block, epsilon parametrisation, mean-free coordinate subspace.
Not ported, all unused by every shipped DiffSBDD config or explicitly out of
scope in the integration plan: GammaNetwork/PositiveLinear
(noise_schedule='learned'), virtual nodes, the auxiliary Lennard-Jones
term and the xh_lig_hat it consumed, SimpleConditionalDDPM,
diversify()/partially_noised_ligand().
forward() returns a dict rather than upstream’s 13-tuple: the task module
in modules/tasks/diffusion_diffsbdd.py is the only consumer, and both
models return the same keys – which is why mode costs the task zero
extra code (en_diffusion.py:465 vs conditional_model.py:326 return
matching tuples upstream, the conditional one substituting 0.0 for the pocket
error).
Classes¶
|
|
2D joint histogram over |
|
|
|
Lookup table of |
Functions¶
|
|
|
|
|
|
Module Contents¶
- class MolecularDiffusion.modules.models.diffsbdd.en_diffusion.ConditionalDDPM(*args: Any, **kwargs: Any)¶
Bases:
EnVariationalDiffusionmode: pocket_conditioning– only the ligand is diffused.- delta_log_px(num_nodes: torch.Tensor) torch.Tensor¶
- forward(ligand: Dict, pocket: Dict) Dict[str, Any]¶
Returns the loss terms; see the module docstring.
- inpaint(ligand: Dict, pocket: Dict, lig_fixed: torch.Tensor, resamplings: int = 1, timesteps: int | None = None, center: str = 'ligand', **_kwargs: Any)¶
RePaint sampling with ligand atoms held fixed (
inpaint.py:147).
- kl_prior(xh_lig, mask_lig, num_nodes)¶
- log_pN(n_lig: torch.Tensor, n_pocket: torch.Tensor) torch.Tensor¶
- log_pxh_given_z0_without_constants(ligand, z_0_lig, eps_lig, net_out_lig, gamma_0, epsilon: float = 1e-10)¶
- noised_representation(xh_lig, xh0_pocket, lig_mask, pocket_mask, gamma_t)¶
- classmethod remove_mean_batch(x_lig, x_pocket, lig_indices, pocket_indices)¶
Subtract only the sampled part’s CoM (the pocket rides along).
- abstractmethod sample(*args: Any, **kwargs: Any)¶
- abstractmethod sample_combined_position_feature_noise(*args: Any, **kwargs: Any)¶
- sample_given_pocket(pocket: Dict, num_nodes_lig: torch.Tensor, timesteps: int | None = None, **_kwargs: Any)¶
De-novo ligand generation inside a fixed pocket.
- abstractmethod sample_normal(*args: Any, **kwargs: Any)¶
- sample_normal_zero_com(mu_lig, xh0_pocket, sigma, lig_mask, pocket_mask)¶
- sample_p_xh_given_z0(z0_lig, xh0_pocket, lig_mask, pocket_mask, batch_size)¶
- sample_p_zs_given_zt(s, t, zt_lig, xh0_pocket, ligand_mask, pocket_mask)¶
- sample_p_zt_given_zs(zs_lig, xh0_pocket, ligand_mask, pocket_mask, gamma_t, gamma_s)¶
- class MolecularDiffusion.modules.models.diffsbdd.en_diffusion.DistributionNodes(histogram: torch.Tensor)¶
2D joint histogram over
(n_ligand_atoms, n_pocket_nodes).Same semantics as upstream
en_diffusion.py:958, but the 178k-entryn_nodes_to_idxdict and the eager per-columnCategoricallists are replaced by row-major arithmetic andtorch.multinomial. Identical maths, built in milliseconds instead of seconds.- log_prob(n_lig: torch.Tensor, n_pocket: torch.Tensor) torch.Tensor¶
log p(N_lig, N_pocket) – the joint model’s
log_pN.
- log_prob_n1_given_n2(n1: torch.Tensor, n2: torch.Tensor) torch.Tensor¶
log p(N_lig | N_pocket) – the conditional model’s
log_pN.
- sample(n_samples: int = 1) Tuple[torch.Tensor, torch.Tensor]¶
- sample_conditional(n1: torch.Tensor | None = None, n2: torch.Tensor | None = None) torch.Tensor¶
Draw one axis given the other.
n2=pocket_sizesis the live path.
- prob¶
- class MolecularDiffusion.modules.models.diffsbdd.en_diffusion.EnVariationalDiffusion(dynamics: torch.nn.Module, atom_nf: int, residue_nf: int, n_dims: int = 3, size_histogram: torch.Tensor | None = None, max_n_lig: int = 107, max_n_pocket: int = 1671, timesteps: int = 500, noise_schedule: str = 'polynomial_2', noise_precision: float = 0.0005, norm_values: Tuple[float, float] = (1.0, 4.0), norm_biases: Tuple[float | None, float] = (None, 0.0))¶
Bases:
torch.nn.Modulemode: joint– ligand and pocket are diffused together.- static SNR(gamma: torch.Tensor) torch.Tensor¶
- alpha(gamma: torch.Tensor, target_tensor: torch.Tensor) torch.Tensor¶
- static assert_mean_zero_with_mask(x: torch.Tensor, node_mask: torch.Tensor, eps: float = 1e-10) None¶
- static cdf_standard_gaussian(x: torch.Tensor) torch.Tensor¶
- compute_x_pred(net_out: torch.Tensor, zt: torch.Tensor, gamma_t: torch.Tensor, batch_mask: torch.Tensor) torch.Tensor¶
- delta_log_px(num_nodes: torch.Tensor) torch.Tensor¶
- forward(ligand: Dict, pocket: Dict) Dict[str, Any]¶
Returns the loss terms; see the module docstring.
- static gaussian_KL(q_mu_minus_p_mu_squared: torch.Tensor, q_sigma: torch.Tensor, p_sigma: torch.Tensor, d) torch.Tensor¶
- static get_repaint_schedule(resamplings: int, jump_length: int, timesteps: int)¶
RePaint jump schedule: denoising steps before each jump back.
- static inflate_batch_array(array: torch.Tensor, target: torch.Tensor) torch.Tensor¶
- inpaint(ligand: Dict, pocket: Dict, lig_fixed: torch.Tensor, pocket_fixed: torch.Tensor, resamplings: int = 1, jump_length: int = 1, timesteps: int | None = None, **_kwargs: Any)¶
RePaint sampling with parts of the system held fixed.
In joint mode this is ALSO the de-novo pocket-conditioned path:
lig_fixed=0/pocket_fixed=1reproduces upstream’slightning_modules.py:814-834. Lugmayr et al., CVPR 2022.
- kl_prior_with_pocket(xh_lig: torch.Tensor, xh_pocket: torch.Tensor, mask_lig: torch.Tensor, mask_pocket: torch.Tensor, num_nodes: torch.Tensor) torch.Tensor¶
- log_constants_p_x_given_z0(n_nodes: torch.Tensor, device) torch.Tensor¶
- log_pN(n_lig: torch.Tensor, n_pocket: torch.Tensor) torch.Tensor¶
- log_pxh_given_z0_without_constants(ligand, z_0_lig, eps_lig, net_out_lig, pocket, z_0_pocket, eps_pocket, net_out_pocket, gamma_0, epsilon: float = 1e-10)¶
- noised_representation(xh_lig: torch.Tensor, xh_pocket: torch.Tensor, lig_mask: torch.Tensor, pocket_mask: torch.Tensor, gamma_t: torch.Tensor)¶
- normalize(ligand: Dict[str, torch.Tensor] | None = None, pocket: Dict[str, torch.Tensor] | None = None)¶
- static remove_mean_batch(x: torch.Tensor, indices: torch.Tensor) torch.Tensor¶
- static sample_center_gravity_zero_gaussian_batch(size, lig_indices: torch.Tensor, pocket_indices: torch.Tensor) torch.Tensor¶
- sample_combined_position_feature_noise(lig_indices: torch.Tensor, pocket_indices: torch.Tensor) Tuple[torch.Tensor, torch.Tensor]¶
- static sample_gaussian(size, device) torch.Tensor¶
- sample_normal(mu_lig: torch.Tensor, mu_pocket: torch.Tensor, sigma: torch.Tensor, lig_mask: torch.Tensor, pocket_mask: torch.Tensor) Tuple[torch.Tensor, torch.Tensor]¶
- sample_p_xh_given_z0(z0_lig, z0_pocket, lig_mask, pocket_mask, batch_size)¶
- sample_p_zs_given_zt(s, t, zt_lig, zt_pocket, ligand_mask, pocket_mask)¶
- sample_p_zt_given_zs(zs_lig, zs_pocket, ligand_mask, pocket_mask, gamma_t, gamma_s)¶
- sigma(gamma: torch.Tensor, target_tensor: torch.Tensor) torch.Tensor¶
- sigma_and_alpha_t_given_s(gamma_t: torch.Tensor, gamma_s: torch.Tensor, target_tensor: torch.Tensor) Tuple[torch.Tensor, torch.Tensor, torch.Tensor]¶
- subspace_dimensionality(input_size: torch.Tensor) torch.Tensor¶
- static sum_except_batch(x: torch.Tensor, indices: torch.Tensor) torch.Tensor¶
- unnormalize(x: torch.Tensor, h_cat: torch.Tensor) Tuple[torch.Tensor, torch.Tensor]¶
- unnormalize_z(z_lig: torch.Tensor, z_pocket: torch.Tensor) Tuple[torch.Tensor, torch.Tensor]¶
- T = 500¶
- atom_nf¶
- dynamics¶
- gamma¶
- n_dims = 3¶
- norm_biases = (None, 0.0)¶
- norm_values = (1.0, 4.0)¶
- num_classes¶
- residue_nf¶
- property size_distribution: DistributionNodes¶
Rebuilt lazily, so
load_state_dicton the buffer takes effect.
- class MolecularDiffusion.modules.models.diffsbdd.en_diffusion.PredefinedNoiseSchedule(noise_schedule: str, timesteps: int, precision: float)¶
Bases:
torch.nn.ModuleLookup table of
gammafor a non-learned schedule.- forward(t: torch.Tensor) torch.Tensor¶
- gamma¶
- timesteps¶
- MolecularDiffusion.modules.models.diffsbdd.en_diffusion.clip_noise_schedule(alphas2: numpy.ndarray, clip_value: float = 0.001) numpy.ndarray¶
- MolecularDiffusion.modules.models.diffsbdd.en_diffusion.cosine_beta_schedule(timesteps: int, s: float = 0.008) numpy.ndarray¶
- MolecularDiffusion.modules.models.diffsbdd.en_diffusion.polynomial_schedule(timesteps: int, s: float = 0.0001, power: float = 3.0) numpy.ndarray¶
1 - x^power;polynomial_2with s=5e-4 is DiffSBDD’s default.