Source code for drugforge.data.operators.state_expanders.stereo_expander

from typing import Literal

from drugforge.data.backend.openeye import clear_SD_data, oechem, oeomega
from drugforge.data.operators.state_expanders.state_expander import StateExpanderBase
from drugforge.data.schema.ligand import Ligand
from pydantic import Field


[docs] class StereoExpander(StateExpanderBase): """ Expand a molecule to stereoisomers using OpenEye Note: The input molecule is only included if it is fully defined. Input molecules with no possible expansions are passed through without an expansion tag set. """ expander_type: Literal["StereoExpander"] = "StereoExpander" stereo_expand_defined: bool = Field( False, description="Expand stereochemistry at defined centers `True` as well as undefined centers", ) def _provenance(self) -> dict[str, str]: return { "oechem": oechem.OEChemGetVersion(), "omega": oeomega.OEOmegaGetVersion(), } def _expand(self, ligands: list[Ligand]) -> list[Ligand]: """ Expand the stereoisomers of the input molecules. Note: Input molecules with no possible expansions are passed through without an expansion tag set. Parameters ---------- ligands: The list of ligands whose states should be expanded. Returns ------- A list of expanded ligand states. """ provenance = self.provenance() omegaOpts = oeomega.OEOmegaOptions() omega = oeomega.OEOmega(omegaOpts) maxcenters = 20 force_flip = self.stereo_expand_defined enum_nitrogen = ( False # WARNING: This creates multiple microstates with same SMILES if True ) warts = False # add suffix for stereoisomers enantiomers = [] for parent_ligand in ligands: # need to clear the SD data otherwise the provenance will break oemol = clear_SD_data(parent_ligand.to_oemol()) for enantiomer in oeomega.OEFlipper( oemol, maxcenters, force_flip, enum_nitrogen, warts ): enantiomer = oechem.OEMol(enantiomer) omega.Build( enantiomer ) # a single conformer needs to be built to fully define stereochemistry enantiomer_ligand = Ligand.from_oemol( enantiomer, **parent_ligand.model_dump(exclude={"provenance", "data"}) ) # if the ligand is the parent ie no possible expansions don't tag it if enantiomer_ligand.fixed_inchikey == parent_ligand.fixed_inchikey: enantiomers.append(parent_ligand) else: enantiomer_ligand.set_expansion( parent_ligand, provenance=provenance ) enantiomers.append(enantiomer_ligand) return enantiomers