def test_single_topology(self): """ It tests the class that generates a OpenFFCompatibleSolvent object for a single topology. """ from .utils import compare_dicts import json TEMPLATE_PARAMS_MAL = get_data_file_path('tests/ligandParams_MAL.txt') # Loads the molecule molecule = Molecule(path=get_data_file_path('ligands/malonate.pdb'), tag='MAL') # Sets forcefield and parameterizes it ff = OpenForceField('openff_unconstrained-1.2.1.offxml') parameters = ff.parameterize(molecule, charge_method='gasteiger') # Initializes topology topology = Topology(molecule, parameters) # Initializes solvent and gets parameters file solvent = OBC2(topology) solvent_dict = solvent.to_dict() # Loads reference dict from template with open(TEMPLATE_PARAMS_MAL, 'r') as f: reference_dict = json.load(f) # Compare the output parameters dict with the reference parameters compare_dicts(reference_dict, solvent_dict)
def test_molecule_tag_assignment(self): """ It tests the molecule tag assignment. """ # Look for UNK tag when dummy Molecule is loaded molecule = Molecule() assert molecule.tag == 'UNK', 'Unexpected atom tag' # Look for the PDB residue name as a tag when a Molecule is loaded # from a PDB file ligand_path = get_data_file_path('ligands/benzene.pdb') molecule = Molecule(ligand_path) assert molecule.tag == 'BNZ', 'Unexpected atom tag' # Look for BEN tag when a Molecule is loaded from a PDB file with # a custom name ligand_path = get_data_file_path('ligands/benzene.pdb') molecule = Molecule(ligand_path, tag='BEN') assert molecule.tag == 'BEN', 'Unexpected atom tag' # Look for UNK tag when a Molecule is loaded from a SMILES tag molecule = Molecule(smiles='c1ccccc1', hydrogens_are_explicit=False) assert molecule.tag == 'UNK', 'Unexpected atom tag' # Look for BNZ tag when a Molecule is loaded from a SMILES tag with # a custom tag molecule = Molecule(smiles='c1ccccc1', tag='BNZ', hydrogens_are_explicit=False) assert molecule.tag == 'BNZ', 'Unexpected atom tag'
def test_molecule_name_assignment(self): """ It tests the molecule name assignment. """ # Look for an empty name when dummy Molecule is loaded molecule = Molecule() assert molecule.name == '', 'Unexpected atom name' # Look for the PDB name when a Molecule is loaded from a PDB file ligand_path = get_data_file_path('ligands/benzene.pdb') molecule = Molecule(ligand_path) assert molecule.name == 'benzene', 'Unexpected atom name' # Look for benzene name when a Molecule is loaded from a PDB file # with a custom name ligand_path = get_data_file_path('ligands/benzene.pdb') molecule = Molecule(ligand_path, name='benzene') assert molecule.name == 'benzene', 'Unexpected atom name' # Look for the SMILES name when a Molecule is loaded from a SMILES tag molecule = Molecule(smiles='c1ccccc1', hydrogens_are_explicit=False) assert molecule.name == 'c1ccccc1', 'Unexpected atom name' # Look for benzene name when a Molecule is loaded from a SMILES tag # with a custom name molecule = Molecule(smiles='c1ccccc1', name='benzene', hydrogens_are_explicit=False) assert molecule.name == 'benzene', 'Unexpected atom name'
def test_writer_OPLS(self): """ It tests the writer attribute of the Impact class using OPLS to parameterize. """ from .utils import parameterize_opls2005 TEMPLATE_METZ_OPLS = get_data_file_path('tests/OPLS_metz') TEMPLATE_MALZ_OPLS = get_data_file_path('tests/OPLS_malz') TEMPLATE_ETLZ_OPLS = get_data_file_path('tests/OPLS_etlz') with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): # Generates the template for methane using OPLS opls2005 = OPLS2005ForceField() pdb_path = get_data_file_path('ligands/methane.pdb') molecule = Molecule(pdb_path) ffld_file = get_data_file_path('tests/MET_ffld_output.txt') parameters = parameterize_opls2005(opls2005, molecule, ffld_file) topology = Topology(molecule, parameters) # Generates the impact template for methane impact = Impact(topology) impact.to_file('metz') # Compare the reference template and the generated template compare_files(file1=TEMPLATE_METZ_OPLS, file2='metz') # Generates the template for malonate using OPLS opls2005 = OPLS2005ForceField() pdb_path = get_data_file_path('ligands/malonate.pdb') molecule = Molecule(pdb_path) ffld_file = get_data_file_path('tests/MAL_ffld_output.txt') parameters = parameterize_opls2005(opls2005, molecule, ffld_file) topology = Topology(molecule, parameters) # Generates the impact template for malonate impact = Impact(topology) impact.to_file('malz') # Compare the reference template and the generated template compare_files(file1=TEMPLATE_MALZ_OPLS, file2='malz') # Generates the template for ethylene using OPLS opls2005 = OPLS2005ForceField() pdb_path = get_data_file_path('ligands/ethylene.pdb') molecule = Molecule(pdb_path, tag='ETL') ffld_file = get_data_file_path('tests/ETL_ffld_output.txt') parameters = parameterize_opls2005(opls2005, molecule, ffld_file) topology = Topology(molecule, parameters) # Generates the impact template for ethylene impact = Impact(topology) impact.to_file('etlz') # Compare the reference template and the generated template compare_files(file1=TEMPLATE_ETLZ_OPLS, file2='etlz')
def test_rmsd(self): """It checks that the rmsd calculator works well.""" from peleffy.topology import Molecule from peleffy.utils.toolkits import RDKitToolkitWrapper from peleffy.utils import get_data_file_path wrapper = RDKitToolkitWrapper() pdb_path = get_data_file_path('ligands/trimethylglycine.pdb') m = Molecule(pdb_path) pdb_path2 = get_data_file_path('ligands/trimethylglycine_moved.pdb') m2 = Molecule(pdb_path2) np.testing.assert_almost_equal(wrapper.get_rmsd(m, m2), 0.3346, decimal=3)
def test_pdb_checkup(self): """It tests the safety check function for PDB files.""" LIGAND_GOOD = get_data_file_path('ligands/ethylene.pdb') LIGAND_ERROR1 = get_data_file_path('tests/ethylene_error1.pdb') LIGAND_ERROR2 = get_data_file_path('tests/ethylene_error2.pdb') LIGAND_ERROR3 = get_data_file_path('tests/ethylene_error3.pdb') LIGAND_ERROR4 = get_data_file_path('tests/ethylene_error4.pdb') # This should work without any complain _ = Molecule(LIGAND_GOOD) # All atom names need to be unique with pytest.raises(Exception): _ = Molecule(LIGAND_ERROR1) # All residue ids must match with pytest.raises(Exception): _ = Molecule(LIGAND_ERROR2) # All residue names must match with pytest.raises(Exception): _ = Molecule(LIGAND_ERROR3) # Check warning message in the logger when connectivity is missing import io from peleffy.utils import Logger import logging from importlib import reload logging.shutdown() reload(logging) log = Logger() log.set_level('WARNING') # Catch logger messages to string buffer with io.StringIO() as buf: log_handler = logging.StreamHandler(buf) log._logger.handlers = list() log._logger.addHandler(log_handler) _ = Molecule(LIGAND_ERROR4) output = buf.getvalue() assert output == "Warning: input PDB has no information " \ + "about the connectivity and this could result in " \ + "an unexpected bond assignment\n"
def test_peleffy_main(self): """It checks the main function of peleffy.""" from peleffy.main import parse_args, main from peleffy.utils import Logger import logging ligand_path = get_data_file_path('ligands/benzene.pdb') with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): # Test default settings args = parse_args([ligand_path]) main(args) logger = Logger() for handler in logger._logger.handlers: assert handler.level == logging.INFO # Test silent settings args = parse_args([ligand_path, '--silent']) main(args) logger = Logger() for handler in logger._logger.handlers: assert handler.level == logging.CRITICAL # Test silent settings args = parse_args([ligand_path, '--debug']) main(args) logger = Logger() for handler in logger._logger.handlers: assert handler.level == logging.DEBUG
def test_input(self): """ It tests that the topology given to Impact() is of the correct format, peleffy.topology.Topology. """ from peleffy.forcefield.parameters import BaseParameterWrapper LIGAND_PATH = 'ligands/benzene.pdb' ligand_path = get_data_file_path(LIGAND_PATH) molecule = Molecule(ligand_path) parameters = BaseParameterWrapper() topology = Topology(molecule, parameters) # Impact() gets nothing as argument with pytest.raises(TypeError): _ = Impact() # Impact() gets a non Topology object with pytest.raises(TypeError): _ = Impact('passing a str instead of a Topology') # This should work _ = Impact(topology)
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' assert molecule.graph is not None, \ 'Molecule\' graph should be initialized'
def test_get_all_childs_of_atom(self): """ It tests the _get_all_childs_of_atom method used in the building process of the Impact template. """ LIGAND_PATH = get_data_file_path('ligands/malonate.pdb') FORCEFIELD_NAME = 'openff_unconstrained-1.2.1.offxml' molecule = Molecule(LIGAND_PATH) openff = OpenForceField(FORCEFIELD_NAME) parameters = openff.parameterize(molecule, charge_method='dummy') topology = Topology(molecule, parameters) impact = Impact(topology) absolute_parent = impact._get_absolute_parent_atom() childs = impact._get_all_childs_of_atom(absolute_parent, 'side chain') assert [a.PDB_name for a in childs] == \ ['_C1_', '_C3_'], \ 'Unexpected side-chain-child atoms: {}'.format(childs) childs = impact._get_all_childs_of_atom(absolute_parent, 'core') assert [a.PDB_name for a in childs] == \ ['_H1_', '_H2_'], \ 'Unexpected core-child atoms: {}'.format(childs)
def test_calculate_cluster_offsets(self): from peleffy.utils import get_data_file_path pdb_path = get_data_file_path('ligands/ethylene.pdb') ffld_path = get_data_file_path("tests/ETL_ffld_output.txt") golden_offsets = [["_C1_", 0.0, 0.0, 0.0], ["_C2_", -1.305, 0.181, -0.014], ["_H1_", 0.72, 0.822, 0.042], ["_H2_", 0.448, -0.988, -0.029], ["_H3_", -1.73, 1.171, 0.015], ["_H4_", -1.936, -0.687, -0.056]] bce_obj = build_mock_BCEConformations(pdb_path, ffld_path) bce_obj.calculate_cluster_offsets(pdb_path) for dih1, dih2 in zip(bce_obj.conformations_library[pdb_path], golden_offsets): assert dih1[0] == dih2[0] np.testing.assert_almost_equal(dih1[1:], dih2[1:], decimal=3)
def test_multiple_topologies_writer(self): """ It tests the class that generates a OpenFFCompatibleSolvent object for multiple topologies. It compares the outcome of the Solvent writer with a reference file. """ from .utils import compare_dicts, parameterize_opls2005 import json TEMPLATE_PARAMS = get_data_file_path('tests/ligandParams.txt') with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): path_OXO = get_data_file_path('tests/MRO_oleic/OXO.pdb') path_OLC = get_data_file_path('tests/MRO_oleic/OLC.pdb') ff = OpenForceField('openff_unconstrained-1.2.1.offxml') opls2005 = OPLS2005ForceField() # Group OXO m_OXO = Molecule(path_OXO) ffld_file = get_data_file_path('tests/OXO_ffld_output.txt') parameters_OXO = parameterize_opls2005(opls2005, m_OXO, ffld_file) topology_OXO = Topology(m_OXO, parameters_OXO) # Acid oleic m_OLC = Molecule(path_OLC) parameters_OLC = ff.parameterize(m_OLC, charge_method='gasteiger') topology_OLC = Topology(m_OLC, parameters_OLC) # Multiple topologies topologies = [topology_OXO, topology_OLC] solvent = OBC2(topologies) solvent.to_file('OBC_parameters.txt') # Loads reference dict from template with open(TEMPLATE_PARAMS, 'r') as f: reference_dict = json.load(f) # Loads the generated template into a dict with open('OBC_parameters.txt', 'r') as f: solvent_dict = json.load(f) # Compare the output parameters dict with the reference parameters compare_dicts(reference_dict, solvent_dict)
def test_PDB_residue_name(self): """ It tests the PDB residue name and checks for consistency with Molecule tag. """ def check_residue_name(name): """Check if residue names are valid in the output PDB file""" with open('molecule.pdb') as f: for line in f: if line.startswith('HETATM'): assert line[17:20] == name, 'Unexpected residue name' ligand_path = get_data_file_path('ligands/benzene.pdb') # Checking tag assignation from PDB molecule = Molecule(ligand_path) with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): assert molecule.tag == 'BNZ', 'Unexpected molecule tag' molecule.to_pdb_file('molecule.pdb') check_residue_name('BNZ') # Checking set_tag() function molecule = Molecule(ligand_path) with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): molecule.set_tag('TAG') assert molecule.tag == 'TAG', 'Unexpected molecule tag' molecule.to_pdb_file('molecule.pdb') check_residue_name('TAG') # Checking default tag assignment from SMILES molecule = Molecule(smiles='c1ccccc1', hydrogens_are_explicit=False) with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): assert molecule.tag == 'UNK', 'Unexpected molecule tag' molecule.to_pdb_file('molecule.pdb') check_residue_name('UNK') # Checking custom tag assignment from SMILES molecule = Molecule(smiles='c1ccccc1', tag='BEN', hydrogens_are_explicit=False) with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): assert molecule.tag == 'BEN', 'Unexpected molecule tag' molecule.to_pdb_file('molecule.pdb') check_residue_name('BEN') # Checking second custom tag assignment from SMILES molecule = Molecule(smiles='c1ccccc1', hydrogens_are_explicit=False) with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): molecule.set_tag('BNZ') assert molecule.tag == 'BNZ', 'Unexpected molecule tag' molecule.to_pdb_file('molecule.pdb') check_residue_name('BNZ')
def test_pdb_initialization(self): """ It checks the initialization from a PDB file. """ ligand_path = get_data_file_path('ligands/ethylene.pdb') molecule = Molecule(ligand_path) # Save it with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): molecule.to_pdb_file('molecule.pdb')
def test_peleffy_default_call(self): """ It checks the default call of peleffy's main function. """ from peleffy.main import run_peleffy LIGAND_PATH = 'ligands/benzene.pdb' ligand_path = get_data_file_path(LIGAND_PATH) with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): run_peleffy(ligand_path, output=tmpdir)
def test_parameterizer(self): """It checks the parameterized method.""" from peleffy.topology import Molecule from peleffy.forcefield import OpenForceField from peleffy.utils import (get_data_file_path, convert_all_quantities_to_string) from .utils import compare_dicts import json # Load molecule 1 molecule = Molecule(get_data_file_path('ligands/methane.pdb')) openff = OpenForceField(self.FORCE_FIELD_NAME) # Obtain force field parameters parameters = openff.parameterize(molecule) writable_parameters = convert_all_quantities_to_string(parameters) reference_file = get_data_file_path( 'tests/MET_openff-1.2.1_parameters.json') with open(reference_file) as f: compare_dicts(writable_parameters, json.load(f)) # Load molecule molecule = Molecule(get_data_file_path('ligands/ethylene.pdb')) openff = OpenForceField(self.FORCE_FIELD_NAME) # Obtain force field parameters parameters = openff.parameterize(molecule) writable_parameters = convert_all_quantities_to_string(parameters) reference_file = get_data_file_path( 'tests/ETL_openff-1.2.1_parameters.json') with open(reference_file) as f: compare_dicts(writable_parameters, json.load(f))
def test_OBCOPLS_writer_ligand(pdbfile, tag_name, ffld_name, reference_file): """ Given a ligand, it tests that the output parameters file corresponds to the refenrece file. Parameters ---------- pdbfile : str The path to the PDB of the ligand to test ffld_name : str The path to the ffld_server's output file reference_file : str The path to reference TXT file compatible with PELE """ with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): # Loads the molecule molecule = Molecule(get_data_file_path(pdbfile), tag=tag_name) # Sets forcefield and parameterizes it opls2005 = OPLS2005ForceField() ffld_file = get_data_file_path(ffld_name) parameters = parameterize_opls2005(opls2005, molecule, ffld_file) # Initializes topology topology = Topology(molecule, parameters) # Initializes solvent and gets parameters file solvent = OPLSOBC(topology) solvent.to_file('OBC_parameters.txt') # Compare the output file with the reference parameters file compare_files_without_order('OBC_parameters.txt', reference_file)
def test_write_dihedral_library(self): import os import tempfile from peleffy.utils import get_data_file_path, temporary_cd pdb_path = get_data_file_path('ligands/ethylene.pdb') ffld_path = get_data_file_path("tests/ETL_ffld_output.txt") bce_obj = build_mock_BCEConformations(pdb_path, ffld_path) bce_obj.calculate_cluster_offsets(pdb_path) calculated_lines = [] with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): bce_obj.save(os.path.join(tmpdir, "ETH.conformation")) with open(os.path.join(tmpdir, "ETH.conformation")) as f: calculated_lines = f.readlines() calculated_lines = calculated_lines[3:] golden_conformation_library_path = get_data_file_path( 'parameters/ETH.conformation') with open(golden_conformation_library_path) as f: golden_lines = f.readlines()[3:] assert golden_lines == calculated_lines
def test_multiple_topologies(self): """ It tests the class that generates a OpenFFCompatibleSolvent object for multiple topologies. """ from .utils import compare_dicts, merge_dicts # Path to multiple non standard residues pdb_path_MAL = get_data_file_path('ligands/malonate.pdb') pdb_path_MET = get_data_file_path('ligands/methane.pdb') # Force Field to parameterize the molecules ff = OpenForceField('openff_unconstrained-1.2.1.offxml') # Topology of malonate mol_MAL = Molecule(path=pdb_path_MAL, tag='MAL') parameters_MAL = ff.parameterize(mol_MAL, charge_method='gasteiger') topology_MAL = Topology(mol_MAL, parameters_MAL) # Topology of methane mol_MET = Molecule(path=pdb_path_MET, tag='MET') parameters_MET = ff.parameterize(mol_MET, charge_method='gasteiger') topology_MET = Topology(mol_MET, parameters_MET) # List containing both topologies topologies = [topology_MAL, topology_MET] # Generate the Solvent parameters dictionaries solvent_MAL_dict = OBC2(topology_MAL).to_dict() solvent_MET_dict = OBC2(topology_MET).to_dict() solvent_dict = OBC2(topologies).to_dict() # Check that merging both single topology dicitionaries we obtain the # same dictionary that using multiple topologies compare_dicts(merge_dicts(solvent_MAL_dict['SolventParameters'], solvent_MET_dict['SolventParameters']), solvent_dict['SolventParameters'])
def test_conformer_setter(self): """It checks the conformer setter of the RDKit toolkit""" from peleffy.topology import Molecule from rdkit import Chem from copy import deepcopy from peleffy.utils import get_data_file_path # Load molecule mol = Molecule(get_data_file_path('ligands/propionic_acid.pdb')) # Choose a dihedral to track dihedral = (0, 1, 2, 3) # Get initial dihedral's theta conformer = mol.rdkit_molecule.GetConformer() initial_theta = Chem.rdMolTransforms.GetDihedralDeg(conformer, *dihedral) if initial_theta < -179: initial_theta += 180.0 elif initial_theta > 179: initial_theta -= 180.0 assert abs(initial_theta - -0.002) < 10e-3, \ 'Unexpected initial theta value' # Get a copy of the rdkit's molecule representation rdkit_mol = deepcopy(mol.rdkit_molecule) # Modify its conformer conformer = rdkit_mol.GetConformer() Chem.rdMolTransforms.SetDihedralDeg(conformer, *dihedral, 90) new_theta = Chem.rdMolTransforms.GetDihedralDeg(conformer, *dihedral) assert abs(new_theta - 89.999) < 10e-3, \ 'Unexpected new theta value' # Set new conformer to peleffy molecule mol.set_conformer(conformer) # Check new set theta value conformer = mol.rdkit_molecule.GetConformer() new_set_theta = Chem.rdMolTransforms.GetDihedralDeg(conformer, *dihedral) assert abs(new_set_theta - 89.999) < 10e-3, \ 'Unexpected new set theta value'
def test_dihedral_angle_2(self): """It checks that the dihedral angle calculator works well.""" from peleffy.topology import Molecule from peleffy.utils.toolkits import RDKitToolkitWrapper from peleffy.utils import get_data_file_path wrapper = RDKitToolkitWrapper() pdb_path = get_data_file_path('ligands/trimethylglycine.pdb') m = Molecule(pdb_path) dihedral_degrees = wrapper.get_dihedral(m, 17, 4, 5, 6, units="degrees") dihedral_rad = wrapper.get_dihedral(m, 17, 4, 5, 6) np.testing.assert_almost_equal(dihedral_degrees, 54.828, decimal=2) np.testing.assert_almost_equal(dihedral_degrees, np.rad2deg(dihedral_rad), decimal=3)
def test_writer_OFF(self): """ It tests the writer attribute of the Impact class using OFF to parameterize. """ TEMPLATE_METZ = get_data_file_path('tests/metz') TEMPLATE_MATZ = get_data_file_path('tests/malz') TEMPLATE_ETLZ = get_data_file_path('tests/etlz') with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): # Generates the template for methane pdb_path = get_data_file_path('ligands/methane.pdb') molecule = Molecule(pdb_path) openff = OpenForceField(self.OPENFF_FORCEFIELD) parameters = openff.parameterize(molecule) topology = Topology(molecule, parameters) # Generates the impact template for methane impact = Impact(topology) impact.to_file('metz') # Compare the reference template and the generated template compare_files(file1=TEMPLATE_METZ, file2='metz') # Generates the template for malonate pdb_path = get_data_file_path('ligands/malonate.pdb') molecule = Molecule(pdb_path) openff = OpenForceField(self.OPENFF_FORCEFIELD) parameters = openff.parameterize(molecule) topology = Topology(molecule, parameters) # Generates the impact template for malonate impact = Impact(topology) impact.to_file('malz') # Compare the reference template and the generated template compare_files(file1=TEMPLATE_MATZ, file2='malz') # Generates the template for ethylene pdb_path = get_data_file_path('ligands/ethylene.pdb') molecule = Molecule( pdb_path, tag='ETL' ) # Note that in this case we are assigning a tag to the molecule which will be used in the Impact template openff = OpenForceField(self.OPENFF_FORCEFIELD) parameters = openff.parameterize(molecule) topology = Topology(molecule, parameters) # Generates the impact template for ethylene impact = Impact(topology) impact.to_file('etlz') # Compare the reference template and the generated template compare_files(file1=TEMPLATE_ETLZ, file2='etlz')
def test_add_topological_elements(self): """ It tests the addition of topological elements to an empty topology. """ from peleffy.topology import Molecule from peleffy.forcefield import OpenForceField from peleffy.forcefield.parameters import BaseParameterWrapper from peleffy.topology import Topology from peleffy.utils import get_data_file_path # Define molecule1 and its topology pdb_path = get_data_file_path('ligands/ethylene.pdb') molecule1 = Molecule(pdb_path) openff = OpenForceField('openff_unconstrained-1.2.1.offxml') parameters1 = openff.parameterize(molecule1) topology1 = Topology(molecule1, parameters1) # Define empty topology2 molecule2 = Molecule() parameters2 = BaseParameterWrapper() topology2 = Topology(molecule2, parameters2) # Add parameters to topology2 for atom in topology1.atoms: topology2.add_atom(atom) for bond in topology1.bonds: topology2.add_bond(bond) for angle in topology1.angles: topology2.add_angle(angle) for proper in topology1.propers: topology2.add_proper(proper) for improper in topology1.impropers: topology2.add_improper(improper) # Verify content of both topologies assert topology1.atoms == topology2.atoms, \ 'The atoms of boths topologies should match' assert topology1.bonds == topology2.bonds, \ 'The bonds of boths topologies should match' assert topology1.angles == topology2.angles, \ 'The angles of boths topologies should match' assert topology1.propers == topology2.propers, \ 'The propers of boths topologies should match' assert topology1.impropers == topology2.impropers, \ 'The impropers of boths topologies should match'
def test_raise_errors(self): """ It tests all the possible errors when geting a molecule from a chain. """ from peleffy.utils.input import PDBFile from peleffy.utils import get_data_file_path PATH_COMPLEX_PDB = get_data_file_path('complexes/LYS_BNZ.pdb') # The chain selected does not exist in the PDB file with pytest.raises(ValueError): PDBreader = PDBFile(PATH_COMPLEX_PDB) _ = PDBreader.get_molecules_from_chain(selected_chain='F') # The chain selected is not an hetero molecule with pytest.raises(ValueError): PDBreader = PDBFile(PATH_COMPLEX_PDB) _ = PDBreader.get_molecules_from_chain(selected_chain='A')
def test_rotamer_core_constraint_adjacency(self): """ It tests the adjacency check up that is performed prior building the rotamer library builder with core constraints. """ LIGAND_PATH = 'ligands/oleic_acid.pdb' ligand_path = get_data_file_path(LIGAND_PATH) # Test adjacent core constraint selection _ = Molecule(ligand_path, core_constraints=[' C8 ', ' C9 ', ' C10']) # Test non adjacent core constraint selection with pytest.raises(ValueError) as e: _ = Molecule(ligand_path, core_constraints=[' C1 ', ' C9 ', ' C10']) assert str(e.value) == 'All atoms in atom constraints must be ' \ + 'adjacent and atom C1 is not'
class OBC2(_OpenFFCompatibleSolvent): """ Implementation of the OBC2 solvent. """ _ff_file = get_data_file_path('forcefields/GBSA_OBC2-1.0.offxml') _name = 'OBC2' def __init__(self, topologies): """ Initializes an OBC2 object. Parameters ---------- topologies : a Topology object or list[Topology object] The molecular topology representation to write as a Impact template Examples -------- Generate the solvent parameters of a molecule >>> from peleffy.topology import Molecule >>> molecule = Molecule('molecule.pdb') >>> from peleffy.forcefield import OpenForceField >>> openff = OpenForceField('openff_unconstrained-1.2.1.offxml') >>> parameters = openff.parameterize(molecule) >>> from peleffy.topology import Topology >>> topology = Topology(molecule, parameters) >>> from peleffy.solvent import OBC2 >>> solvent = OBC2(topology) >>> solvent.to_file('OBC_parameters.txt') """ super().__init__(topologies)
def test_peleffy_custom_call(self): """ It checks the custom call of peleffy's main function. """ from peleffy.main import run_peleffy LIGAND_PATH = 'ligands/benzene.pdb' CUSTOM_FORCEFIELD_NAME = 'openff_unconstrained-1.2.0.offxml' ligand_path = get_data_file_path(LIGAND_PATH) with tempfile.TemporaryDirectory() as tmpdir: with temporary_cd(tmpdir): run_peleffy(ligand_path, forcefield_name=CUSTOM_FORCEFIELD_NAME, resolution=10, charge_method='gasteiger', output=tmpdir, with_solvent=True, as_datalocal=True)
def test_pdb_parsers(self): """It checks that the PDB parsers from RDKit are correctly working.""" from rdkit.Chem.rdmolfiles import MolToPDBBlock from peleffy.utils.toolkits import RDKitToolkitWrapper from peleffy.utils import get_data_file_path wrapper = RDKitToolkitWrapper() pdb_path = get_data_file_path('ligands/benzene.pdb') with open(pdb_path) as f: pdb_block = f.read() rdkit_mol1 = wrapper.from_pdb(pdb_path) rdkit_mol2 = wrapper.from_pdb_block(pdb_block) block1 = MolToPDBBlock(rdkit_mol1) block2 = MolToPDBBlock(rdkit_mol2) assert block1 == block2, 'Unexpected pair of RDKit molecules'
def test_pdb_fixer_logger_messages(self): """It checks the logger messages of the PDB fixer.""" from peleffy.utils import Logger import io molecule = Molecule(fix_pdb=True) # Check logger messages path3 = get_data_file_path('tests/ligSUV_no_elements3.pdb') import logging # Force a hard reset of logging library and the logger it manages from importlib import reload logging.shutdown() reload(logging) # Initiate logger log = Logger() # Try the default level (INFO) # Catch logger messages to string buffer with io.StringIO() as buf: # Add custom handler to logger log_handler = logging.StreamHandler(buf) log._logger.handlers = list() log._logger.addHandler(log_handler) _ = molecule._read_and_fix_pdb(path3) # Get string from buffer output = buf.getvalue() assert output == "Warning: input PDB has no information " \ + "about atom elements and they were inferred from " \ + "atom names. " \ + "Please, verify that the resulting elements are " \ + "correct\n" \ + "Error: PDB could not be fixed\n"
def test_get_absolute_parent_atom(self): """ It tests the _get_absolute_parent_atom method used in the building process of the Impact template. """ LIGAND_PATH = get_data_file_path('ligands/malonate.pdb') FORCEFIELD_NAME = 'openff_unconstrained-1.2.1.offxml' molecule = Molecule(LIGAND_PATH) openff = OpenForceField(FORCEFIELD_NAME) parameters = openff.parameterize(molecule, charge_method='dummy') topology = Topology(molecule, parameters) impact = Impact(topology) absolute_parent = impact._get_absolute_parent_atom() assert absolute_parent.PDB_name == '_C2_', \ 'Unexpected absolute parent atom: {}'.format(absolute_parent)