예제 #1
0
def _generate_conformers(
    molecule: Molecule, max_confs: int = 800, rms_threshold: float = 1.0
) -> Molecule:
    """Generate conformations for the supplied molecule.

    Parameters
    ----------
    molecule
        Molecule for which to generate conformers
    max_confs
        Max number of conformers to generate.
    rms_threshold
        The minimum RMS value [Angstrom] at which two conformers are considered redundant
        and one is deleted.

    Returns
    -------
        A new multi-conformer molecule with up to max_confs conformers.
    """

    from simtk import unit

    molecule = copy.deepcopy(molecule)

    # Store the atom map separately in case it gets removed / mangled by a TK.
    atom_map = molecule.properties.pop("atom_map", None)

    # Canonically order the atoms in the molecule before generating the conformer.
    # This helps ensure the same conformers are generated for the same molecules
    # independently of their atom order.
    canonical_molecule = molecule.canonical_order_atoms()

    canonical_molecule.generate_conformers(
        n_conformers=max_confs, rms_cutoff=rms_threshold * unit.angstrom
    )

    _, canonical_map = Molecule.are_isomorphic(
        canonical_molecule, molecule, return_atom_map=True
    )

    molecule = canonical_molecule.remap(canonical_map)

    # Restore the atom map.
    if atom_map is not None:
        molecule.properties["atom_map"] = atom_map

    return molecule
예제 #2
0
    def _prepare_molecule(
        cls,
        molecule: Molecule,
        functional_groups: Dict[str, str],
        keep_non_rotor_ring_substituents: bool,
    ) -> Tuple[Molecule, Stereochemistries, FunctionalGroups, RingSystems]:
        """Prepare a molecule for fragmentation.

        This involves canonically ordering the molecule, determining the stereochemistry
        of any stereocenters, detecting any functional groups which should be preserved,
        and finding any ring systems which should be preserved.

        Parameters
        ----------
        molecule
            The parent molecule that should be fragmented.
        functional_groups:
            A dictionary of SMARTS of functional groups that should not be fragmented.
        keep_non_rotor_ring_substituents:
            If True, will always keep all non rotor substituents on ring.

        Returns
        -------
            The prepared molecule to fragment, its stereochemistry, and the functional
            groups and ring systems it contains that should not be fragmented.
        """

        # Canonically order the molecule to try and make the fragmentation more
        # deterministic.
        molecule: Molecule = molecule.canonical_order_atoms()
        molecule.properties["atom_map"] = {i: i + 1 for i in range(molecule.n_atoms)}

        # Keep track of stereo to make sure it does not flip
        stereo = cls._find_stereo(molecule)

        # Find the functional groups and ring systems which should not be fragmented.
        found_functional_groups = cls._find_functional_groups(
            molecule, functional_groups
        )
        found_ring_systems = cls._find_ring_systems(
            molecule, found_functional_groups, keep_non_rotor_ring_substituents
        )

        return molecule, stereo, found_functional_groups, found_ring_systems