Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mol from rdkit #106

Merged
merged 6 commits into from
Nov 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion devtools/conda/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ requirements:
- networkx
- rdkit
- ambertools
- openforcefield==0.7.1
- openforcefield==0.8.0

about:
home: https://github.com/martimunicoy/peleffy
Expand Down
2 changes: 1 addition & 1 deletion devtools/envs/standard.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ dependencies:
- coverage < 5.0
- ambertools
- rdkit
- openforcefield ==0.7.1
- openforcefield ==0.8.0
2 changes: 2 additions & 0 deletions docs/releasehistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ New features
- `PR #86 <https://github.com/martimunicoy/peleffy/pull/86>`_: New method to check the input PDB prior building the molecule.
- `PR #94 <https://github.com/martimunicoy/peleffy/pull/94>`_: New method for the OPLS OBC parameters.
- `PR #92 <https://github.com/martimunicoy/peleffy/pull/92>`_: New parameter to skip the stereochemistry assignment (and the checking from the OpenFF toolkit).
- `PR #106 <https://github.com/martimunicoy/peleffy/pull/106>`_: New method to initialize a Molecule object directly from an RDKit and OpenFF molecular representations.

API-breaking changes
""""""""""""""""""""
Expand All @@ -31,6 +32,7 @@ Tests added
- `PR #94 <https://github.com/martimunicoy/peleffy/pull/94>`_: Adds tests to validate the OPLS OBC parameters generator.
- `PR #92 <https://github.com/martimunicoy/peleffy/pull/92>`_: New test to check the behaviour of the allow_undefined_stereo parameter.
- `PR #97 <https://github.com/martimunicoy/peleffy/pull/97>`_: Includes tests for the new Topology container class.
- `PR #106 <https://github.com/martimunicoy/peleffy/pull/106>`_: Adds tests to check the RDKit and OpenFF molecular initializers.

1.0.0 - Full compatibility for OPLS2005 and OpenFF dihedrals and rotamer library improvements
---------------------------------------------------------------------------------------------
Expand Down
48 changes: 48 additions & 0 deletions peleffy/tests/test_molecule.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,51 @@ def test_undefined_stereo(self):
with tempfile.TemporaryDirectory() as tmpdir:
with temporary_cd(tmpdir):
mol.to_pdb_file('molecule.pdb')

def test_from_rdkit(self):
"""
It checks the initialization of a peleffy Molecule from an RDKit
molecular representation.
"""
from rdkit import Chem

pdb_path = get_data_file_path('ligands/malonate.pdb')
rdkit_molecule = Chem.MolFromPDBFile(pdb_path, removeHs=False)
molecule = Molecule.from_rdkit(rdkit_molecule)

assert molecule._rdkit_molecule is not None, \
'Unexpected molecule representation found, it is not initialized'
assert molecule._off_molecule is not None, \
'Unexpected molecule representation found, it is not initialized'

ref_pdb_atom_names = [' O1 ', ' C1 ', ' O2 ', ' C2 ', ' C3 ',
' O3 ', ' O4 ', ' H1 ', ' H2 ', ' H3 ']
pdb_atom_names = molecule.get_pdb_atom_names()

assert pdb_atom_names == ref_pdb_atom_names, \
'Unexpected PDB atom names found in the resulting Molecule ' \
+ 'representation'

def test_from_openff(self):
"""
It checks the initialization of a peleffy Molecule from an OpenFF
molecular representation.
"""
from openforcefield.topology import Molecule as OpenFFMolecule

openff_molecule = OpenFFMolecule.from_smiles('C(C(=O)[O-])C(=O)[OH]')

molecule = Molecule.from_openff(openff_molecule)

assert molecule._rdkit_molecule is not None, \
'Unexpected molecule representation found, it is not initialized'
assert molecule._off_molecule is not None, \
'Unexpected molecule representation found, it is not initialized'

ref_pdb_atom_names = [' C1 ', ' C2 ', ' O1 ', ' O2 ', ' C3 ',
' O3 ', ' O4 ', ' H1 ', ' H2 ', ' H3 ']
pdb_atom_names = molecule.get_pdb_atom_names()

assert pdb_atom_names == ref_pdb_atom_names, \
'Unexpected PDB atom names found in the resulting Molecule ' \
+ 'representation'
155 changes: 155 additions & 0 deletions peleffy/topology/molecule.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,161 @@ def get_conformer(self):

return rdkit_toolkit.get_coordinates(self)

@staticmethod
def from_rdkit(rdkit_molecule, rotamer_resolution=30,
exclude_terminal_rotamers=True, name='', tag='UNK',
connectivity_template=None, core_constraints=[],
allow_undefined_stereo=False):
"""
It initializes and returns a peleffy Molecule representation
from an RDKit molecular representation.

Parameters
----------
rdkit_molecule : an rdkit.Chem.rdchem.Mol object
The RDKit's Molecule object to use to initialize a peleffy
Molecule object
rotamer_resolution : float
The resolution in degrees to discretize the rotamer's
conformational space. Default is 30
exclude_terminal_rotamers : bool
Whether to exclude terminal rotamers when generating the
rotamers library or not
name : str
The molecule name
tag : str
The molecule tag. It must be a 3-character string
connectivity_template : an rdkit.Chem.rdchem.Mol object
A molecule represented with RDKit to use when assigning the
connectivity of this Molecule object
core_constraints : list[int or str]
It defines the list of atoms to constrain in the core, thus,
the core will be forced to contain them. Atoms can be specified
through integers that match the atom index or strings that
match with the atom PDB name
allow_undefined_stereo : bool
Whether to allow a molecule with undefined stereochemistry
to be defined or try to assign the stereochemistry and
raise a complaint if not possible. Default is False

Returns
-------
molecule : an peleffy.topology.Molecule
The resulting peleffy's Molecule object

Examples
--------

Load a molecule from an RDKit molecular representation

>>> from rdkit import Chem

>>> rdkit_molecule = Chem.MolFromPDBFile(pdb_path, removeHs=False)

>>> from peleffy.topology import Molecule

>>> molecule = Molecule.from_rdkit(rdkit_molecule)

"""
molecule = Molecule(
rotamer_resolution=30,
exclude_terminal_rotamers=exclude_terminal_rotamers,
name=name, tag=tag,
connectivity_template=connectivity_template,
core_constraints=core_constraints,
allow_undefined_stereo=allow_undefined_stereo)

logger = Logger()

logger.info(' - Initializing molecule from an RDKit '
+ 'molecular representation')
molecule._initialize()
molecule._rdkit_molecule = rdkit_molecule

logger.info(' - Representing molecule with the Open Force Field '
+ 'Toolkit')
openforcefield_toolkit = OpenForceFieldToolkitWrapper()
molecule._off_molecule = openforcefield_toolkit.from_rdkit(molecule)

return molecule

@staticmethod
def from_openff(openff_molecule, rotamer_resolution=30,
exclude_terminal_rotamers=True, name='', tag='UNK',
connectivity_template=None, core_constraints=[],
allow_undefined_stereo=False):
"""
It initializes and returns a peleffy Molecule representation
from an OpenForceField molecular representation.

Parameters
----------
openff_molecule : an openforcefield.topology.Molecule object
The OpenForceField's Molecule to use to initialize a peleffy
Molecule object
rotamer_resolution : float
The resolution in degrees to discretize the rotamer's
conformational space. Default is 30
exclude_terminal_rotamers : bool
Whether to exclude terminal rotamers when generating the
rotamers library or not
name : str
The molecule name
tag : str
The molecule tag. It must be a 3-character string
connectivity_template : an rdkit.Chem.rdchem.Mol object
A molecule represented with RDKit to use when assigning the
connectivity of this Molecule object
core_constraints : list[int or str]
It defines the list of atoms to constrain in the core, thus,
the core will be forced to contain them. Atoms can be specified
through integers that match the atom index or strings that
match with the atom PDB name
allow_undefined_stereo : bool
Whether to allow a molecule with undefined stereochemistry
to be defined or try to assign the stereochemistry and
raise a complaint if not possible. Default is False

Returns
-------
molecule : an peleffy.topology.Molecule
The resulting peleffy's Molecule object

Examples
--------

Load a molecule from an RDKit molecular representation

>>> from rdkit import Chem

>>> rdkit_molecule = Chem.MolFromPDBFile(pdb_path)

>>> from peleffy.topology import Molecule

>>> molecule = Molecule.from_rdkit(rdkit_molecule)

"""
molecule = Molecule(
rotamer_resolution=30,
exclude_terminal_rotamers=exclude_terminal_rotamers,
name=name, tag=tag,
connectivity_template=connectivity_template,
core_constraints=core_constraints,
allow_undefined_stereo=allow_undefined_stereo)

logger = Logger()

logger.info(' - Initializing molecule from an OpenFF '
+ 'molecular representation')
molecule._initialize()
molecule._off_molecule = openff_molecule

logger.info(' - Generating RDKit molecular representation with '
+ 'the Open Force Field Toolkit')
molecule._rdkit_molecule = openff_molecule.to_rdkit()

return molecule

@property
def rotamer_resolution(self):
"""
Expand Down