예제 #1
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')
예제 #2
0
    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
예제 #3
0
    def run_ffld_server(self, molecule):
        """
        It calls Schrodinger's ffld_server to parameterize a molecule
        with OPLS.

        .. todo ::

           * Review PlopRotTemp's atom type fixes. Should we apply them here?

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

        Returns
        -------
        ffld_output : str
            The ffld_server output
        """

        ffld_server_exec = self.path_to_ffld_server()

        with tempfile.TemporaryDirectory() as tmpdir:
            with temporary_cd(tmpdir):

                self._rdkit_toolkit_wrapper.to_pdb_file(
                    molecule, tmpdir + '/molecule.pdb')

                subprocess.check_output([
                    ffld_server_exec, "-ipdb", "molecule.pdb", "-version",
                    "14", "-print_parameters", "-out_file", "parameters.txt"
                ])

                with open('parameters.txt') as parameters_file:
                    return parameters_file.read()
예제 #4
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')
예제 #5
0
    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')
예제 #6
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')
예제 #7
0
    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')
예제 #8
0
    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)
예제 #9
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')
예제 #10
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)
예제 #11
0
    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)
예제 #12
0
    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
예제 #13
0
        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)
예제 #14
0
    def compute_partial_charges(self, molecule, method='am1bcc'):
        """
        It computes the partial charges using antechamber.

        Parameters
        ----------
        molecule : an peleffy.topology.Molecule
            The peleffy's Molecule object
        method : str
            The name of the method to use. One of ['gasteiger', 'am1bcc'].
            If None, 'am1bcc' will be used

        Returns
        -------
        charges : simtk.unit.Quantity
            The array of partial charges

        Raises
        ------
        ChargeMethodUnavailableError if the requested charge method can not
            be handled by this toolkit
        ChargeCalculationError if the charge method is supported by this
            toolkit, but fails
        """

        SUPPORTED_CHARGE_METHODS = {
            'am1bcc': {
                'antechamber_keyword': 'bcc'
            },
            'gasteiger': {
                'antechamber_keyword': 'gas'
            }
        }

        if method not in SUPPORTED_CHARGE_METHODS:
            raise ChargeMethodUnavailableError(
                'partial_charge_method ' +
                '{} is not available from '.format(method) +
                'AmberToolsToolkitWrapper. Available charge methods are ' +
                list(SUPPORTED_CHARGE_METHODS.keys()))

        off_molecule = molecule.off_molecule

        with tempfile.TemporaryDirectory() as tmpdir:
            with temporary_cd(tmpdir):
                net_charge = off_molecule.total_charge / \
                    unit.elementary_charge

                self._rdkit_toolkit_wrapper.to_sdf_file(
                    molecule, tmpdir + '/molecule.sdf')

                subprocess.check_output([
                    "antechamber", "-i", "molecule.sdf", "-fi", "sdf", "-o",
                    "charged.ac", "-fo", "ac", "-pf", "yes", "-dr", "n", "-c",
                    SUPPORTED_CHARGE_METHODS[method]['antechamber_keyword'],
                    "-nc",
                    str(net_charge)
                ])
                # Write out just charges
                subprocess.check_output([
                    "antechamber", "-dr", "n", "-i", "charged.ac", "-fi", "ac",
                    "-o", "charged2.ac", "-fo", "ac", "-c", "wc", "-cf",
                    "charges.txt", "-pf", "yes"
                ])

                if not os.path.exists('charges.txt'):
                    # TODO: copy files into local directory to aid debugging?
                    raise ChargeCalculationError(
                        "Antechamber/sqm partial charge calculation failed on "
                        "molecule {} (SMILES {})".format(
                            off_molecule.name, off_molecule.to_smiles()))

                # Read the charges
                with open('charges.txt', 'r') as infile:
                    contents = infile.read()

                text_charges = contents.split()
                charges = np.zeros([off_molecule.n_atoms], np.float64)
                for index, token in enumerate(text_charges):
                    charges[index] = float(token)

        charges = unit.Quantity(charges, unit.elementary_charge)

        assert len(charges) == len(molecule.rdkit_molecule.GetAtoms()), \
            'Partial charge computation failed as the length of ' \
            + 'resulting partial charges does not match with the ' \
            + 'number of atoms in molecule'

        return charges
예제 #15
0
    def test_folder_creation(self):
        """
        It tests the folder creation of the OutputPathHandler class.
        """
        from peleffy.utils import OutputPathHandler, temporary_cd
        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')

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

            # Test path getter without folder creation
            path = output_handler.get_rotamer_library_path(
                create_missing_folders=False)
            path_dir = os.path.dirname(path)
            assert os.path.isdir(path_dir) is False, \
                'This directory should not exist'
            path = output_handler.get_impact_template_path(
                create_missing_folders=False)
            path_dir = os.path.dirname(path)
            assert os.path.isdir(path_dir) is False, \
                'This directory should not exist'
            path = output_handler.get_solvent_template_path(
                create_missing_folders=False)
            path_dir = os.path.dirname(path)
            assert os.path.isdir(path_dir) is False, \
                'This directory should not exist'
            path = output_handler.get_conformation_library_path(
                create_missing_folders=False)
            path_dir = os.path.dirname(path)
            assert os.path.isdir(path_dir) is False, \
                'This directory should not exist'

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

                # Test path getter with folder creation
                path = output_handler.get_rotamer_library_path(
                    create_missing_folders=True)
                path_dir = os.path.dirname(path)
                assert os.path.isdir(path_dir) is True, \
                    'This directory should exist'
                path = output_handler.get_impact_template_path(
                    create_missing_folders=True)
                path_dir = os.path.dirname(path)
                assert os.path.isdir(path_dir) is True, \
                    'This directory should exist'
                path = output_handler.get_solvent_template_path(
                    create_missing_folders=True)
                path_dir = os.path.dirname(path)
                assert os.path.isdir(path_dir) is True, \
                    'This directory should exist'
                path = output_handler.get_conformation_library_path(
                    create_missing_folders=True)
                path_dir = os.path.dirname(path)
                assert os.path.isdir(path_dir) is True, \
                    'This directory should exist'