Exemple #1
0
    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'
Exemple #2
0
    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'
Exemple #3
0
    def test_undefined_stereo(self):
        """
        It checks the behaviour when ignoring the stereochemistry
        in the Molecule initialization.
        """
        from openff.toolkit.utils.toolkits import UndefinedStereochemistryError
        from peleffy.forcefield import OpenForceField

        # This should crash due to an undefined stereochemistry error
        with pytest.raises(UndefinedStereochemistryError):
            mol = Molecule(smiles='CN(C)CCC=C1c2ccccc2CCc3c1cccc3',
                           hydrogens_are_explicit=False)

        # This now should work
        mol = Molecule(smiles='CN(C)CCC=C1c2ccccc2CCc3c1cccc3',
                       allow_undefined_stereo=True,
                       hydrogens_are_explicit=False)

        # And we can parameterize it
        ff = OpenForceField('openff_unconstrained-1.2.1.offxml')
        ff.parameterize(mol, charge_method='gasteiger')

        # Save it
        with tempfile.TemporaryDirectory() as tmpdir:
            with temporary_cd(tmpdir):
                mol.to_pdb_file('molecule.pdb')
    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')
Exemple #5
0
    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_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')
Exemple #7
0
    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)
Exemple #8
0
    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"
Exemple #9
0
    def test_charge_calculator_selector(self):
        """It checks the charge calculator selector."""
        from peleffy.topology import Molecule
        from peleffy.forcefield import OpenForceField
        import peleffy

        dummy_mol = Molecule()

        # Check default selection
        openff = OpenForceField(self.FORCE_FIELD_NAME)
        calculator = openff._get_charge_calculator(None, dummy_mol)

        assert isinstance(
            calculator,
            peleffy.forcefield.calculators.Am1bccCalculator), \
            'Invalid default charge calculator: ' \
            + '{}'.format(type(calculator))

        # Check custom selection 1
        openff = OpenForceField(self.FORCE_FIELD_NAME)
        calculator = openff._get_charge_calculator('gasteiger', dummy_mol)

        assert isinstance(
            calculator,
            peleffy.forcefield.calculators.GasteigerCalculator), \
            'Invalid custom selection 1 for the charge calculator'

        # Check custom selection 1
        openff = OpenForceField(self.FORCE_FIELD_NAME)
        calculator = openff._get_charge_calculator('opls2005', dummy_mol)

        assert isinstance(
            calculator,
            peleffy.forcefield.calculators.OPLSChargeCalculator), \
            'Invalid custom selection 2 for the charge calculator'
    def display_outlayers_above(self, threshold):
        """Displays the molecules that overcome the given threshold."""

        from peleffy.topology import Molecule
        from IPython.display import display

        compound_ids, smiles_tags, _ = self._read_dataset()
        cid_to_smiles = dict()

        for cid, smiles_tag in zip(compound_ids, smiles_tags):
            cid_to_smiles[cid] = smiles_tag

        for cid, diff, expv in zip(self.results['cids'],
                                   self.results['differences'],
                                   self.results['experimental_values']):
            if abs(diff - expv) > 10:
                smiles = cid_to_smiles[cid]
                print('-' * max((len(cid) + len(smiles) + 3), 47))
                print(cid, '-', smiles)
                print('-' * max((len(cid) + len(smiles) + 3), 47))
                mol = Molecule(smiles=smiles)
                print(' - Experimental difference: ' +
                      '{: 10.1f} kcal/mol'.format(expv))
                print(' - Predicted difference:    ' +
                      '{: 10.1f} kcal/mol'.format(diff))
                print(' - Absolute error:          ' +
                      '{: 10.1f} kcal/mol'.format(abs(diff - expv)))
                display(mol)
Exemple #11
0
    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 _generate_parameters(self):
        """
		It generates the parameters of the molecule (from the input_file) as DataLocal in the output folder.
		"""
        import peleffy
        from peleffy.topology import Molecule
        from peleffy.template import Impact
        from peleffy.solvent import OBC2
        from peleffy.main import handle_output_paths
        import os

        # Forcefield and charges method
        forcefield = 'openff_unconstrained-1.2.0.offxml'
        charges_method = 'am1bcc'

        # Create representation of a particular molecule
        PATH_molecule = os.path.join(os.getcwd(), 'output', 'ligand.pdb')
        molecule = Molecule(PATH_molecule)

        # Saving paths
        rotamer_library_output_path, impact_output_path, solvent_output_path = \
         handle_output_paths(molecule = molecule, output =os.path.join(os.getcwd(),'output'), as_datalocal = True )

        # Generate its rotamer library
        rotamer_library = peleffy.topology.RotamerLibrary(molecule)
        rotamer_library.to_file(rotamer_library_output_path)

        # Generate its parameters and template file
        molecule.parameterize(forcefield, charges_method=charges_method)
        impact = Impact(molecule)
        impact.write(impact_output_path)

        # Generate its solvent parameters
        solvent = OBC2(molecule)
        solvent.to_json_file(solvent_output_path)
    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_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)
Exemple #15
0
    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'
Exemple #16
0
    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)
Exemple #17
0
    def test_smiles_initialization(self):
        """
        It checks the initialization from a SMILES tag.
        """
        molecule = Molecule(smiles='c1ccccc1', hydrogens_are_explicit=False)

        # Save it
        with tempfile.TemporaryDirectory() as tmpdir:
            with temporary_cd(tmpdir):
                molecule.to_pdb_file('molecule.pdb')
Exemple #18
0
    def test_pdb_fixer(self):
        """
        It checks the PDB fixer prior parsing a PDB input file for
        a peleffy Molecule.
        """
        from .utils import compare_blocks

        # Check default
        molecule = Molecule()

        assert molecule.fix_pdb is True, \
            'Unexpected default settings for the PDB fixer'

        # Activate fixer
        molecule = Molecule(fix_pdb=True)

        ref_path = get_data_file_path('tests/ligSUV_fixed.pdb')
        path1 = get_data_file_path('tests/ligSUV_no_elements1.pdb')
        path2 = get_data_file_path('tests/ligSUV_no_elements2.pdb')

        ref_pdb_block = molecule._read_and_fix_pdb(ref_path)
        pdb_block1 = molecule._read_and_fix_pdb(path1)
        pdb_block2 = molecule._read_and_fix_pdb(path2)

        compare_blocks(ref_pdb_block, pdb_block1, (76, 78))
        compare_blocks(ref_pdb_block, pdb_block2, (76, 78))

        # Deactivate fixer
        molecule = Molecule(fix_pdb=False)

        ref_path = get_data_file_path('tests/ligSUV_fixed.pdb')
        path1 = get_data_file_path('tests/ligSUV_no_elements1.pdb')
        path2 = get_data_file_path('tests/ligSUV_no_elements2.pdb')

        ref_pdb_block = molecule._read_and_fix_pdb(ref_path)
        pdb_block1 = molecule._read_and_fix_pdb(path1)
        pdb_block2 = molecule._read_and_fix_pdb(path2)

        with pytest.raises(AssertionError):
            compare_blocks(ref_pdb_block, pdb_block1, (76, 78))

        with pytest.raises(AssertionError):
            compare_blocks(ref_pdb_block, pdb_block2, (76, 78))
Exemple #19
0
    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'
Exemple #20
0
    def test_non_datalocal_paths(self):
        """
        It tests the non-datalocal paths assignment.
        """
        from peleffy.utils import OutputPathHandler
        from peleffy.forcefield import OpenForceField

        # Load benzene molecule
        molecule = Molecule(smiles='c1ccccc1', name='benzene', tag='BNZ',
                            hydrogens_are_explicit=False)

        # Load force field
        openff = OpenForceField('openff_unconstrained-1.2.1.offxml')

        # Molecule's tag
        tag = molecule.tag

        # Initialize output handler without output_path
        output_handler = OutputPathHandler(molecule, openff,
                                           as_datalocal=False)

        # Validate output paths
        assert output_handler.get_rotamer_library_path() == \
            './{}.rot.assign'.format(tag.upper()), \
            'Unexpected default rotamer library path'
        assert output_handler.get_impact_template_path() == \
            './{}z'.format(tag.lower()), \
            'Unexpected default Impact template path'
        assert output_handler.get_solvent_template_path() == \
            './ligandParams.txt', \
            'Unexpected default solvent parameters path'
        assert output_handler.get_conformation_library_path() == \
            './{}.conformation'.format(tag.upper()), \
            'Unexpected default conformation library path'

        # Initialize output handler with an output_path set
        with tempfile.TemporaryDirectory() as tmpdir:
            output_handler = OutputPathHandler(
                molecule, openff, as_datalocal=False,
                output_path=os.path.join(tmpdir, 'output'))

            assert output_handler.get_rotamer_library_path() == \
                os.path.join(tmpdir, 'output',
                             '{}.rot.assign'.format(tag.upper())), \
                'Unexpected default rotamer library path'
            assert output_handler.get_impact_template_path() == \
                os.path.join(tmpdir, 'output', '{}z'.format(tag.lower())), \
                'Unexpected default Impact template path'
            assert output_handler.get_solvent_template_path() == \
                os.path.join(tmpdir, 'output', 'ligandParams.txt'), \
                'Unexpected default solvent parameters path'
            assert output_handler.get_conformation_library_path() == \
                os.path.join(tmpdir, 'output',
                             '{}.conformation'.format(tag.upper())), \
                'Unexpected default conformation library path'
Exemple #21
0
    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')
Exemple #22
0
    def test_molecule_display(self):
        """
        It checks the visual representation of the molecule in a
        Jupyter notebook.
        """

        from IPython.display import display

        molecule = Molecule(smiles='c1ccccc1', hydrogens_are_explicit=False)

        # This should not raise any Exception
        display(molecule)
    def _generate_parameters(self, smiles, mol_id, output_path,
                             forcefield='openff_unconstrained-1.2.0.offxml',
                             charges_method='am1bcc'):
        """
        It generates the parameters of the molecule (from the input_file)
        as DataLocal in the output folder.

        Parameters
        ----------
        smiles : str
            The smiles tag representing the molecule to minimize
        mol_id : str
            Unique id to identify the molecule to minimize
        output_path : str
            The output path where parameters will be saved
        forcefield : str
            The Open Force Field force field to generate the parameters
            with
        charges_method : str
            The charges method to calculate the partial charges with
        """
        import peleffy
        from peleffy.topology import Molecule
        from peleffy.template import Impact
        from peleffy.solvent import OBC2
        from peleffy.main import handle_output_paths
        import os

        # Create representation of a particular molecule
        molecule = Molecule(smiles=smiles, name=mol_id, tag='UNL')

        # Save molecule to PDB file
        molecule.to_pdb_file(os.path.join(output_path, 'ligand.pdb'))

        # Saving paths
        rotamer_library_output_path, impact_output_path, \
            solvent_output_path = handle_output_paths(molecule=molecule,
                                                      output=output_path,
                                                      as_datalocal=True)

        # Generate its rotamer library
        rotamer_library = peleffy.topology.RotamerLibrary(molecule)
        rotamer_library.to_file(rotamer_library_output_path)

        # Generate its parameters and template file
        molecule.parameterize(forcefield, charges_method=charges_method)
        impact = Impact(molecule)
        impact.write(impact_output_path)

        # Generate its solvent parameters
        solvent = OBC2(molecule)
        solvent.to_json_file(solvent_output_path)
Exemple #24
0
    def test_empty_parameters(self):
        """
        It tests the initialization of a Topology object with an empty
        parameters wrapper.
        """

        from peleffy.topology import Molecule
        from peleffy.forcefield.parameters import BaseParameterWrapper
        from peleffy.topology import Topology

        molecule = Molecule()
        parameters = BaseParameterWrapper()
        Topology(molecule, parameters)
Exemple #25
0
    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))
Exemple #26
0
    def test_parameterizer(self):
        """It checks the parameterized method."""

        from peleffy.topology import Molecule
        from peleffy.forcefield import OPLS2005ForceField
        from peleffy.utils import (get_data_file_path,
                                   convert_all_quantities_to_string)
        from .utils import compare_dicts, parameterize_opls2005
        import json

        # Load molecule 1
        molecule = Molecule(get_data_file_path('ligands/methane.pdb'))
        oplsff = OPLS2005ForceField()
        ffld_file = get_data_file_path('tests/MET_ffld_output.txt')

        parameters = parameterize_opls2005(oplsff, molecule, ffld_file)

        writable_parameters = convert_all_quantities_to_string(parameters)

        reference_file = get_data_file_path(
            'tests/MET_opls2005_parameters.json')

        with open(reference_file) as f:
            compare_dicts(writable_parameters, json.load(f))

        # Load molecule 1
        molecule = Molecule(get_data_file_path('ligands/ethylene.pdb'))
        oplsff = OPLS2005ForceField()
        ffld_file = get_data_file_path('tests/ETL_ffld_output.txt')

        parameters = parameterize_opls2005(oplsff, molecule, ffld_file)

        writable_parameters = convert_all_quantities_to_string(parameters)

        reference_file = get_data_file_path(
            'tests/ETL_opls2005_parameters.json')

        with open(reference_file) as f:
            compare_dicts(writable_parameters, json.load(f))
Exemple #27
0
    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'])
Exemple #28
0
    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 build_mock_BCEConformations(pdb_file, ffld_file):
    from peleffy.topology import Molecule, BCEConformations
    from peleffy.forcefield import ForceFieldSelector
    from peleffy.topology import Topology
    from .utils import parameterize_opls2005

    molecule = Molecule(pdb_file)
    ff_selector = ForceFieldSelector()
    forcefield = ff_selector.get_by_name("opls2005")
    parameters = parameterize_opls2005(forcefield,
                                       molecule,
                                       ffld_file,
                                       charge_method="opls2005")
    topology = Topology(molecule, parameters)
    return BCEConformations(topology, "")
Exemple #30
0
    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)