<commit_before>"""
Conformer generation.
"""

import numpy as np
from typing import Any, List, Optional
from deepchem.utils.typing import RDKitMol


class ConformerGenerator(object):
  """
  Generate molecule conformers.

  Notes
  -----
  Procedure
  1. Generate a pool of conformers.
  2. Minimize conformers.
  3. Prune conformers using an RMSD threshold.

  Note that pruning is done _after_ minimization, which differs from the
  protocol described in the references [1]_ [2]_.

  References
  ----------
  .. [1] http://rdkit.org/docs/GettingStartedInPython.html#working-with-3d-molecules
  .. [2] http://pubs.acs.org/doi/full/10.1021/ci2004658
  
  Note
  ----
  This class requires RDKit to be installed.
  """

  def __init__(self,
               max_conformers: int = 1,
               rmsd_threshold: float = 0.5,
               force_field: str = 'uff',
               pool_multiplier: int = 10):
    """
    Parameters
    ----------
    max_conformers : int, optional (default 1)
      Maximum number of conformers to generate (after pruning).
    rmsd_threshold : float, optional (default 0.5)
      RMSD threshold for pruning conformers. If None or negative, no
      pruning is performed.
    force_field : str, optional (default 'uff')
      Force field to use for conformer energy calculation and
      minimization. Options are 'uff', 'mmff94', and 'mmff94s'.
    pool_multiplier : int, optional (default 10)
      Factor to multiply by max_conformers to generate the initial
      conformer pool. Since conformers are pruned after energy
      minimization, increasing the size of the pool increases the chance
      of identifying max_conformers unique conformers.
    """
    self.max_conformers = max_conformers
    if rmsd_threshold is None or rmsd_threshold < 0:
      rmsd_threshold = -1.
    self.rmsd_threshold = rmsd_threshold
    self.force_field = force_field
    self.pool_multiplier = pool_multiplier

  def __call__(self, mol: RDKitMol) -> RDKitMol:
    """
    Generate conformers for a molecule.

    Parameters
    ----------
    mol: RDKit Mol
      RDKit Mol object

    Returns
    -------
    mol: RDKit Mol
      A new RDKit Mol containing the chosen conformers, sorted by
      increasing energy.
    """
    return self.generate_conformers(mol)

  def generate_conformers(self, mol: RDKitMol) -> RDKitMol:
    """
    Generate conformers for a molecule.

    This function returns a copy of the original molecule with embedded
    conformers.

    Parameters
    ----------
    mol: RDKit Mol
      RDKit Mol object

    Returns
    -------
    mol: RDKit Mol
      A new RDKit Mol containing the chosen conformers, sorted by
      increasing energy.
    """

    # initial embedding
    mol = self.embed_molecule(mol)
    if not mol.GetNumConformers():
      msg = 'No conformers generated for molecule'
      if mol.HasProp('_Name'):
        name = mol.GetProp('_Name')
        msg += ' "{}".'.format(name)
      else:
        msg += '.'
      raise RuntimeError(msg)

    # minimization and pruning
    self.minimize_conformers(mol)
    mol = self.prune_conformers(mol)

    return mol

  def embed_molecule(self, mol: RDKitMol) -> RDKitMol:
    """
    Generate conformers, possibly with pruning.

    Parameters
    ----------
    mol: RDKit Mol
      RDKit Mol object

    Returns
    -------
    mol: RDKit Mol
      RDKit Mol object with embedded multiple conformers.
    """
    try:
      from rdkit import Chem
      from rdkit.Chem import AllChem
    except ModuleNotFoundError:
      raise ValueError("This function requires RDKit to be installed.")

    mol = Chem.AddHs(mol)  # add hydrogens
    n_confs = self.max_conformers * self.pool_multiplier
    AllChem.EmbedMultipleConfs(mol, numConfs=n_confs, pruneRmsThresh=-1.)
    return mol

  def get_molecule_force_field(self,
                               mol: RDKitMol,
                               conf_id: Optional[int] = None,
                               **kwargs) -> Any:
    """
    Get a force field for a molecule.

    Parameters
    ----------
    mol: RDKit Mol
      RDKit Mol object with embedded conformers.
    conf_id : int, optional
      ID of the conformer to associate with the force field.
    kwargs : dict, optional
      Keyword arguments for force field constructor.

    Returns
    -------
    ff: rdkit.ForceField
      RDKit force field instance for a molecule.
    """
    try:
      from rdkit.Chem import AllChem
    except ModuleNotFoundError:
      raise ValueError("This function requires RDKit to be installed.")

    if self.force_field == 'uff':
      ff = AllChem.UFFGetMoleculeForceField(mol, confId=conf_id, **kwargs)
    elif self.force_field.startswith('mmff'):<commit_msg>:pencil: fix docs<commit_after>"""
Conformer generation.
"""

import numpy as np
from typing import Any, List, Optional
from deepchem.utils.typing import RDKitMol


class ConformerGenerator(object):
  """
  Generate molecule conformers.

  Notes
  -----
  Procedure
  1. Generate a pool of conformers.
  2. Minimize conformers.
  3. Prune conformers using an RMSD threshold.

  Note that pruning is done _after_ minimization, which differs from the
  protocol described in the references [1]_ [2]_.

  References
  ----------
  .. [1] http://rdkit.org/docs/GettingStartedInPython.html#working-with-3d-molecules
  .. [2] http://pubs.acs.org/doi/full/10.1021/ci2004658
  
  Note
  ----
  This class requires RDKit to be installed.
  """

  def __init__(self,
               max_conformers: int = 1,
               rmsd_threshold: float = 0.5,
               force_field: str = 'uff',
               pool_multiplier: int = 10):
    """
    Parameters
    ----------
    max_conformers : int, optional (default 1)
      Maximum number of conformers to generate (after pruning).
    rmsd_threshold : float, optional (default 0.5)
      RMSD threshold for pruning conformers. If None or negative, no
      pruning is performed.
    force_field : str, optional (default 'uff')
      Force field to use for conformer energy calculation and
      minimization. Options are 'uff', 'mmff94', and 'mmff94s'.
    pool_multiplier : int, optional (default 10)
      Factor to multiply by max_conformers to generate the initial
      conformer pool. Since conformers are pruned after energy
      minimization, increasing the size of the pool increases the chance
      of identifying max_conformers unique conformers.
    """
    self.max_conformers = max_conformers
    if rmsd_threshold is None or rmsd_threshold < 0:
      rmsd_threshold = -1.
    self.rmsd_threshold = rmsd_threshold
    self.force_field = force_field
    self.pool_multiplier = pool_multiplier

  def __call__(self, mol: RDKitMol) -> RDKitMol:
    """
    Generate conformers for a molecule.

    Parameters
    ----------
    mol: RDKit Mol
      RDKit Mol object

    Returns
    -------
    mol: RDKit Mol
      A new RDKit Mol containing the chosen conformers, sorted by
      increasing energy.
    """
    return self.generate_conformers(mol)

  def generate_conformers(self, mol: RDKitMol) -> RDKitMol:
    """
    Generate conformers for a molecule.

    This function returns a copy of the original molecule with embedded
    conformers.

    Parameters
    ----------
    mol: RDKit Mol
      RDKit Mol object

    Returns
    -------
    mol: RDKit Mol
      A new RDKit Mol containing the chosen conformers, sorted by
      increasing energy.
    """

    # initial embedding
    mol = self.embed_molecule(mol)
    if not mol.GetNumConformers():
      msg = 'No conformers generated for molecule'
      if mol.HasProp('_Name'):
        name = mol.GetProp('_Name')
        msg += ' "{}".'.format(name)
      else:
        msg += '.'
      raise RuntimeError(msg)

    # minimization and pruning
    self.minimize_conformers(mol)
    mol = self.prune_conformers(mol)

    return mol

  def embed_molecule(self, mol: RDKitMol) -> RDKitMol:
    """
    Generate conformers, possibly with pruning.

    Parameters
    ----------
    mol: RDKit Mol
      RDKit Mol object

    Returns
    -------
    mol: RDKit Mol
      RDKit Mol object with embedded multiple conformers.
    """
    try:
      from rdkit import Chem
      from rdkit.Chem import AllChem
    except ModuleNotFoundError:
      raise ValueError("This function requires RDKit to be installed.")

    mol = Chem.AddHs(mol)  # add hydrogens
    n_confs = self.max_conformers * self.pool_multiplier
    AllChem.EmbedMultipleConfs(mol, numConfs=n_confs, pruneRmsThresh=-1.)
    return mol

  def get_molecule_force_field(self,
                               mol: RDKitMol,
                               conf_id: Optional[int] = None,
                               **kwargs) -> Any:
    """
    Get a force field for a molecule.

    Parameters
    ----------
    mol: RDKit Mol
      RDKit Mol object with embedded conformers.
    conf_id : int, optional
      ID of the conformer to associate with the force field.
    kwargs : dict, optional
      Keyword arguments for force field constructor.

    Returns
    -------
    ff: RDKit ForceField
      RDKit force field instance for a molecule.
    """
    try:
      from rdkit.Chem import AllChem
    except ModuleNotFoundError:
      raise ValueError("This function requires RDKit to be installed.")

    if self.force_field == 'uff':
      ff = AllChem.UFFGetMoleculeForceField(mol, confId=conf_id, **kwargs)
    elif self.force_field.startswith('mmff'):
{'fraction_non_alphanumeric': 0.09241656104773975, 'fraction_numerical': 0.008027038445289396, 'mean_word_length': 2.325957147874956, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '490976', 'n_tokens_mistral': 2945, 'n_tokens_neox': 2719, 'n_words': 890}