Exemplo n.º 1
0
    def test_explicit_hydrogens(self):
        """
        It checks initialization of a Molecule with the explicit hydrogens
        flag.
        """

        # Load ethane from SMILES with implicit hydrogen atoms
        molecule = Molecule(smiles='CC')
        atom_names = molecule.get_pdb_atom_names()

        for atom_name in atom_names:
            assert 'H' not in atom_name, 'Unexpected H in molecule without ' \
                + 'explicit hydrogen atoms and hydrogens_are_explicit ' \
                + 'set to True'

        # Load ethane from SMILES without explicit hydrogen atoms
        molecule = Molecule(smiles='CC', hydrogens_are_explicit=False)
        atom_names = molecule.get_pdb_atom_names()

        found_hydrogen = False
        for atom_name in atom_names:
            if 'H' in atom_name:
                found_hydrogen = True
                break
        
        assert found_hydrogen, 'Hydrogen not found regardless of setting ' \
            + 'hydrogens_are_explicit to False'

        # Load ethane from SMILES with explicit hydrogen atoms
        molecule = Molecule(smiles='[H]C([H])([H])C([H])([H])([H])',
                            hydrogens_are_explicit=True)
        atom_names = molecule.get_pdb_atom_names()

        found_hydrogen = False
        for atom_name in atom_names:
            if 'H' in atom_name:
                found_hydrogen = True
                break

        assert found_hydrogen, 'Hydrogen not found regardless of being ' \
                               + 'explicitly defined in the SMILES tag'

        # Load ethane from PDB with implicit hydrogen atoms
        pdb_path = get_data_file_path('tests/ethane_noH.pdb')
        molecule = Molecule(pdb_path,
                            hydrogens_are_explicit=True)
        atom_names = molecule.get_pdb_atom_names()

        for atom_name in atom_names:
            assert 'H' not in atom_name, 'Unexpected H in molecule without ' \
                + 'explicit hydrogen atoms and hydrogens_are_explicit ' \
                + 'set to True'

        # Load ethane from PDB without explicit hydrogen atoms
        pdb_path = get_data_file_path('tests/ethane_noH.pdb')
        molecule = Molecule(pdb_path,
                            hydrogens_are_explicit=False)
        atom_names = molecule.get_pdb_atom_names()

        found_hydrogen = False
        for atom_name in atom_names:
            if 'H' in atom_name:
                found_hydrogen = True
                break

        assert found_hydrogen, 'Hydrogen not found regardless of setting ' \
            + 'hydrogens_are_explicit to False'
Exemplo n.º 2
0
    def test_datalocal_paths_for_offopls(self):
        """
        It tests the datalocal paths assignment for OpenFF-OPLS2005
        force field.
        """
        from peleffy.utils import OutputPathHandler
        from peleffy.forcefield import OpenFFOPLS2005ForceField

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

        # Load force field
        hybridff = OpenFFOPLS2005ForceField(
            'openff_unconstrained-1.2.1.offxml')

        # Molecule's tag
        tag = molecule.tag

        # Initialize output handler without output_path
        output_handler = OutputPathHandler(molecule, hybridff,
                                           as_datalocal=True)

        # Validate output paths
        assert output_handler.get_rotamer_library_path(
            create_missing_folders=False) == \
            './DataLocal/LigandRotamerLibs/' \
            + '{}.rot.assign'.format(tag.upper()), \
            'Unexpected default rotamer library path'
        assert output_handler.get_impact_template_path(
            create_missing_folders=False) == \
            './DataLocal/Templates/OpenFF/Parsley/' \
            + '{}z'.format(tag.lower()), \
            'Unexpected default Impact template path'
        assert output_handler.get_solvent_template_path(
            create_missing_folders=False) == \
            './DataLocal/OBC/ligandParams.txt', \
            'Unexpected default solvent parameters path'
        assert output_handler.get_conformation_library_path(
            create_missing_folders=False) == \
            './DataLocal/Conformations/' \
            + '{}.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, hybridff, as_datalocal=True,
                output_path=os.path.join(tmpdir, 'output'))

            assert output_handler.get_rotamer_library_path(
                create_missing_folders=False) == \
                os.path.join(tmpdir, 'output', 'DataLocal/LigandRotamerLibs/'
                             + '{}.rot.assign'.format(tag.upper())), \
                'Unexpected default rotamer library path'
            assert output_handler.get_impact_template_path(
                create_missing_folders=False) == \
                os.path.join(tmpdir, 'output', 'DataLocal/Templates/'
                             + 'OpenFF/Parsley/{}z'.format(tag.lower())), \
                'Unexpected default Impact template path'
            assert output_handler.get_solvent_template_path(
                create_missing_folders=False) == \
                os.path.join(tmpdir, 'output',
                             'DataLocal/OBC/ligandParams.txt'), \
                'Unexpected default solvent parameters path'
            assert output_handler.get_conformation_library_path(
                create_missing_folders=False) == \
                os.path.join(tmpdir, 'output/DataLocal/Conformations/' \
                + '{}.conformation'.format(tag.upper())), \
                'Unexpected default conformation library path'

        # Initialize output handler without output_path
        output_handler = OutputPathHandler(molecule, hybridff,
                                           as_datalocal=True)

        # Set force field source for nonbonding parameters
        hybridff.set_nonbonding_parameters('opls2005')

        # Validate output paths
        assert output_handler.get_rotamer_library_path(
            create_missing_folders=False) == \
            './DataLocal/LigandRotamerLibs/' \
            + '{}.rot.assign'.format(tag.upper()), \
            'Unexpected default rotamer library path'
        assert output_handler.get_impact_template_path(
            create_missing_folders=False) == \
            './DataLocal/Templates/OPLS2005/HeteroAtoms/' \
            + '{}z'.format(tag.lower()), \
            'Unexpected default Impact template path'
        assert output_handler.get_solvent_template_path(
            create_missing_folders=False) == \
            './DataLocal/OBC/ligandParams.txt', \
            'Unexpected default solvent parameters path'
        assert output_handler.get_conformation_library_path(
            create_missing_folders=False) == \
            './DataLocal/Conformations/' \
            + '{}.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, hybridff, as_datalocal=True,
                output_path=os.path.join(tmpdir, 'output'))

            assert output_handler.get_rotamer_library_path(
                create_missing_folders=False) == \
                os.path.join(tmpdir, 'output', 'DataLocal/LigandRotamerLibs/'
                             + '{}.rot.assign'.format(tag.upper())), \
                'Unexpected default rotamer library path'
            assert output_handler.get_impact_template_path(
                create_missing_folders=False) == \
                os.path.join(tmpdir, 'output', 'DataLocal/Templates/OPLS2005/'
                             + 'HeteroAtoms/{}z'.format(tag.lower())), \
                'Unexpected default Impact template path'
            assert output_handler.get_solvent_template_path(
                create_missing_folders=False) == \
                os.path.join(tmpdir, 'output',
                             'DataLocal/OBC/ligandParams.txt'), \
                'Unexpected default solvent parameters path'
            assert output_handler.get_conformation_library_path(
                create_missing_folders=False) == \
                os.path.join(tmpdir, 'output',
                             'DataLocal/Conformations/',
                             '{}.conformation'.format(tag.upper())), \
                'Unexpected default conformation library path'
Exemplo n.º 3
0
    def test_PDB_connectivity_template(self):
        """
        It tests the initialization of an peleffy's Molecule representation
        from a PDB file without connectivity and a connectivity template.
        """
        # Initialize an empty Molecule object
        molecule = Molecule()
        assert molecule.connectivity_template is None, \
            'Unexpected connectivity template'

        # Initialize a Molecule from a PDB without connectivity and
        # without a connectivity template
        ligand_path = get_data_file_path(
            'ligands/benzene_without_connectivity.pdb')
        molecule = Molecule(ligand_path)

        expected_bond_ids = [(1, 0, False), (2, 1, False), (3, 2, False),
                             (4, 3, False), (5, 4, False), (5, 0, False),
                             (6, 0, False), (7, 1, False), (8, 2, False),
                             (9, 3, False), (10, 4, False), (11, 5, False)]

        for bond in molecule.rdkit_molecule.GetBonds():
            bond_id = (bond.GetBeginAtomIdx(), bond.GetEndAtomIdx(),
                       bond.GetIsAromatic())
            assert bond_id in expected_bond_ids, 'Unexpected bond id ' \
                + '{}'.format(bond_id)

        # Initialize a Molecule from a PDB without connectivity but with
        # a connectivity template
        template_path = get_data_file_path(
            'ligands/benzene.pdb')
        template = Molecule(template_path)
        ligand_path = get_data_file_path(
            'ligands/benzene_without_connectivity.pdb')
        molecule = Molecule(ligand_path,
                            connectivity_template=template.rdkit_molecule)

        expected_bond_ids = [(1, 0, True), (2, 1, True), (3, 2, True),
                             (4, 3, True), (5, 4, True), (5, 0, True),
                             (6, 0, False), (7, 1, False), (8, 2, False),
                             (9, 3, False), (10, 4, False), (11, 5, False)]

        for bond in molecule.rdkit_molecule.GetBonds():
            bond_id = (bond.GetBeginAtomIdx(), bond.GetEndAtomIdx(),
                       bond.GetIsAromatic())
            assert bond_id in expected_bond_ids, 'Unexpected bond id ' \
                + '{}'.format(bond_id)

        # Initialize a Molecule from a PDB with connectivity and with
        # a connectivity template
        template_path = get_data_file_path(
            'ligands/benzene.pdb')
        template = Molecule(template_path)
        ligand_path = get_data_file_path(
            'ligands/benzene.pdb')
        molecule = Molecule(ligand_path,
                            connectivity_template=template.rdkit_molecule)

        expected_bond_ids = [(0, 1, True), (1, 2, True), (2, 3, True),
                             (3, 4, True), (4, 5, True), (0, 5, True),
                             (0, 6, False), (1, 7, False), (2, 8, False),
                             (3, 9, False), (4, 10, False), (5, 11, False)]

        for bond in molecule.rdkit_molecule.GetBonds():
            bond_id = (bond.GetBeginAtomIdx(), bond.GetEndAtomIdx(),
                       bond.GetIsAromatic())
            assert bond_id in expected_bond_ids, 'Unexpected bond id ' \
                + '{}'.format(bond_id)
Exemplo n.º 4
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')
Exemplo n.º 5
0
    def test_terminal_rotamer_filtering(self):
        """
        It tests the rotamer library builder when the terminal rotatable bonds
        are ignored.
        """
        LIGAND_PATH = 'ligands/oleic_acid.pdb'

        ligand_path = get_data_file_path(LIGAND_PATH)
        molecule = Molecule(ligand_path, exclude_terminal_rotamers=True)

        rotamers_per_branch = molecule.rotamers

        assert len(rotamers_per_branch) == 2, "Found an invalid number " + \
            "of branches: {}".format(len(rotamers_per_branch))

        atom_list_1 = list()
        atom_list_2 = list()
        rotamers = rotamers_per_branch[0]
        for rotamer in rotamers:
            atom_list_1.append(set([rotamer.index1, rotamer.index2]))

        rotamers = rotamers_per_branch[1]
        for rotamer in rotamers:
            atom_list_2.append(set([rotamer.index1, rotamer.index2]))

        EXPECTED_INDICES_1 = [
            set([9, 10]),
            set([8, 9]),
            set([7, 8]),
            set([6, 7]),
            set([5, 6]),
            set([2, 5]),
            set([0, 2]),
            set([0, 1])
        ]

        EXPECTED_INDICES_2 = [
            set([12, 11]),
            set([12, 13]),
            set([13, 14]),
            set([14, 15]),
            set([15, 16]),
            set([16, 17]),
            set([17, 18])
        ]

        where_1 = list()
        for atom_pair in atom_list_1:
            if atom_pair in EXPECTED_INDICES_1:
                where_1.append(1)
            elif atom_pair in EXPECTED_INDICES_2:
                where_1.append(2)
            else:
                where_1.append(0)

        where_2 = list()
        for atom_pair in atom_list_2:
            if atom_pair in EXPECTED_INDICES_1:
                where_2.append(1)
            elif atom_pair in EXPECTED_INDICES_2:
                where_2.append(2)
            else:
                where_2.append(0)

        assert (all(i == 1 for i in where_1)
                and all(i == 2 for i in where_2)) or \
            (all(i == 2 for i in where_1)
             and all(i == 1 for i in where_2)), "Invalid rotamer library " + \
            "{}, {}".format(where_1, where_2)

        assert (all(i == 1 for i in where_1)
                and all(i == 2 for i in where_2)
                and len(where_1) == len(EXPECTED_INDICES_1)
                and len(where_2) == len(EXPECTED_INDICES_2)) or \
               (all(i == 2 for i in where_1)
                and all(i == 1 for i in where_2)
                and len(where_1) == len(EXPECTED_INDICES_2)
                and len(where_2) == len(EXPECTED_INDICES_1)), "Unexpected " + \
            "number of rotamers"
Exemplo n.º 6
0
    def test_rotamer_core_constraint(self):
        """
        It tests the rotamer library builder when constraining its core
        to contain a specific atom.
        """

        LIGAND_PATH = 'ligands/oleic_acid.pdb'
        ligand_path = get_data_file_path(LIGAND_PATH)

        # Test atom index constraint
        molecule = Molecule(ligand_path,
                            core_constraints=[
                                19,
                            ],
                            exclude_terminal_rotamers=False)

        rotamers_per_branch = molecule.rotamers

        assert len(rotamers_per_branch) == 1, "Found an invalid number " + \
            "of branches: {}".format(len(rotamers_per_branch))

        atom_list = list()
        for rotamer in rotamers_per_branch[0]:
            atom_list.append(set([rotamer.index1, rotamer.index2]))

        EXPECTED_INDICES = [
            set([18, 19]),
            set([17, 18]),
            set([16, 17]),
            set([15, 16]),
            set([14, 15]),
            set([13, 14]),
            set([12, 13]),
            set([11, 12]),
            set([9, 10]),
            set([8, 9]),
            set([7, 8]),
            set([6, 7]),
            set([5, 6]),
            set([2, 5]),
            set([0, 2]),
            set([0, 1])
        ]

        assert len(atom_list) == len(EXPECTED_INDICES), "Unexpected " + \
            "number of rotamers"

        assert all(atom_pair in EXPECTED_INDICES for atom_pair in atom_list), \
            "Invalid rotamer library"

        # Test PDB atom name constraint
        molecule = Molecule(ligand_path,
                            core_constraints=[
                                ' C18',
                            ],
                            exclude_terminal_rotamers=False)

        rotamers_per_branch = molecule.rotamers

        assert len(rotamers_per_branch) == 1, "Found an invalid number " + \
            "of branches: {}".format(len(rotamers_per_branch))

        atom_list = list()
        for rotamer in rotamers_per_branch[0]:
            atom_list.append(set([rotamer.index1, rotamer.index2]))

        EXPECTED_INDICES = [
            set([18, 19]),
            set([17, 18]),
            set([16, 17]),
            set([15, 16]),
            set([14, 15]),
            set([13, 14]),
            set([12, 13]),
            set([11, 12]),
            set([9, 10]),
            set([8, 9]),
            set([7, 8]),
            set([6, 7]),
            set([5, 6]),
            set([2, 5]),
            set([0, 2]),
            set([0, 1])
        ]

        assert len(atom_list) == len(EXPECTED_INDICES), "Unexpected " + \
            "number of rotamers"

        assert all(atom_pair in EXPECTED_INDICES for atom_pair in atom_list), \
            "Invalid rotamer library"

        # Test core constraint with terminal exclusion
        molecule = Molecule(ligand_path,
                            core_constraints=[
                                ' C18',
                            ],
                            exclude_terminal_rotamers=True)

        rotamers_per_branch = molecule.rotamers

        assert len(rotamers_per_branch) == 1, "Found an invalid number " + \
            "of branches: {}".format(len(rotamers_per_branch))

        atom_list = list()
        for rotamer in rotamers_per_branch[0]:
            atom_list.append(set([rotamer.index1, rotamer.index2]))

        EXPECTED_INDICES = [
            set([17, 18]),
            set([16, 17]),
            set([15, 16]),
            set([14, 15]),
            set([13, 14]),
            set([12, 13]),
            set([11, 12]),
            set([9, 10]),
            set([8, 9]),
            set([7, 8]),
            set([6, 7]),
            set([5, 6]),
            set([2, 5]),
            set([0, 2]),
            set([0, 1])
        ]

        assert len(atom_list) == len(EXPECTED_INDICES), "Unexpected " + \
            "number of rotamers"

        assert all(atom_pair in EXPECTED_INDICES for atom_pair in atom_list), \
            "Invalid rotamer library"

        # Test core constraint with a central core
        molecule = Molecule(ligand_path,
                            core_constraints=[
                                ' C9 ',
                            ],
                            exclude_terminal_rotamers=True)

        rotamers_per_branch = molecule.rotamers

        assert len(rotamers_per_branch) == 2, "Found an invalid number " + \
            "of branches: {}".format(len(rotamers_per_branch))

        atom_list_1 = list()
        atom_list_2 = list()
        rotamers = rotamers_per_branch[0]
        for rotamer in rotamers:
            atom_list_1.append(set([rotamer.index1, rotamer.index2]))

        rotamers = rotamers_per_branch[1]
        for rotamer in rotamers:
            atom_list_2.append(set([rotamer.index1, rotamer.index2]))

        EXPECTED_INDICES_1 = [
            set([9, 10]),
            set([8, 9]),
            set([7, 8]),
            set([6, 7]),
            set([5, 6]),
            set([2, 5]),
            set([0, 2]),
            set([0, 1])
        ]

        EXPECTED_INDICES_2 = [
            set([12, 11]),
            set([12, 13]),
            set([13, 14]),
            set([14, 15]),
            set([15, 16]),
            set([16, 17]),
            set([17, 18])
        ]

        where_1 = list()
        for atom_pair in atom_list_1:
            if atom_pair in EXPECTED_INDICES_1:
                where_1.append(1)
            elif atom_pair in EXPECTED_INDICES_2:
                where_1.append(2)
            else:
                where_1.append(0)

        where_2 = list()
        for atom_pair in atom_list_2:
            if atom_pair in EXPECTED_INDICES_1:
                where_2.append(1)
            elif atom_pair in EXPECTED_INDICES_2:
                where_2.append(2)
            else:
                where_2.append(0)

        assert (all(i == 1 for i in where_1)
                and all(i == 2 for i in where_2)) or \
            (all(i == 2 for i in where_1)
             and all(i == 1 for i in where_2)), "Invalid rotamer library " + \
            "{}, {}".format(where_1, where_2)

        assert (all(i == 1 for i in where_1)
                and all(i == 2 for i in where_2)
                and len(where_1) == len(EXPECTED_INDICES_1)
                and len(where_2) == len(EXPECTED_INDICES_2)) or \
               (all(i == 2 for i in where_1)
                and all(i == 1 for i in where_2)
                and len(where_1) == len(EXPECTED_INDICES_2)
                and len(where_2) == len(EXPECTED_INDICES_1)), "Unexpected " + \
            "number of rotamers"

        # Test core constraint with a multiple central core
        molecule = Molecule(ligand_path,
                            core_constraints=[' C8 ', ' C9 ', ' C10'],
                            exclude_terminal_rotamers=True)

        rotamers_per_branch = molecule.rotamers

        assert len(rotamers_per_branch) == 2, "Found an invalid number " + \
            "of branches: {}".format(len(rotamers_per_branch))

        atom_list_1 = list()
        atom_list_2 = list()
        rotamers = rotamers_per_branch[0]
        for rotamer in rotamers:
            atom_list_1.append(set([rotamer.index1, rotamer.index2]))

        rotamers = rotamers_per_branch[1]
        for rotamer in rotamers:
            atom_list_2.append(set([rotamer.index1, rotamer.index2]))

        EXPECTED_INDICES_1 = [
            set([8, 9]),
            set([7, 8]),
            set([6, 7]),
            set([5, 6]),
            set([2, 5]),
            set([0, 2]),
            set([0, 1])
        ]

        EXPECTED_INDICES_2 = [
            set([12, 11]),
            set([12, 13]),
            set([13, 14]),
            set([14, 15]),
            set([15, 16]),
            set([16, 17]),
            set([17, 18])
        ]

        where_1 = list()
        for atom_pair in atom_list_1:
            if atom_pair in EXPECTED_INDICES_1:
                where_1.append(1)
            elif atom_pair in EXPECTED_INDICES_2:
                where_1.append(2)
            else:
                where_1.append(0)

        where_2 = list()
        for atom_pair in atom_list_2:
            if atom_pair in EXPECTED_INDICES_1:
                where_2.append(1)
            elif atom_pair in EXPECTED_INDICES_2:
                where_2.append(2)
            else:
                where_2.append(0)

        assert (all(i == 1 for i in where_1)
                and all(i == 2 for i in where_2)) or \
            (all(i == 2 for i in where_1)
             and all(i == 1 for i in where_2)), "Invalid rotamer library " + \
            "{}, {}".format(where_1, where_2)

        assert (all(i == 1 for i in where_1)
                and all(i == 2 for i in where_2)
                and len(where_1) == len(EXPECTED_INDICES_1)
                and len(where_2) == len(EXPECTED_INDICES_2)) or \
               (all(i == 2 for i in where_1)
                and all(i == 1 for i in where_2)
                and len(where_1) == len(EXPECTED_INDICES_2)
                and len(where_2) == len(EXPECTED_INDICES_1)), "Unexpected " + \
            "number of rotamers"
Exemplo n.º 7
0
def run_peleffy(pdb_file,
                forcefield_name=DEFAULT_OFF_FORCEFIELD,
                resolution=DEFAULT_RESOLUTION,
                charge_method=DEFAULT_CHARGE_METHOD,
                charges_from_file=None,
                chain=None,
                exclude_terminal_rotamers=True,
                output=None,
                with_solvent=False,
                as_datalocal=False,
                conformation_path=None):
    """
    It runs peleffy.

    Parameters
    ----------
    pdb_file : str
        The path to the pdb_file to parameterize with peleffy
    forcefield_name : str
        The name of an OpenForceField's forcefield
    resolution : float
        The resolution in degrees for the rotamer library. Default is 30
    charge_method : str
        The name of the method to use to compute partial charges. Default
        is 'am1bcc'
    charges_from_file : str
        The file containing the partial charges to assign to the
        molecule. Default is None
    chain : str
        Chain to the molecule if the PDB contains multiple molecules.
    exclude_terminal_rotamers : bool
        Whether to exclude terminal rotamers or not
    output : str
        Path where output files will be saved
    with_solvent : bool
        Whether to generate and save the solvent parameters for the input
        molecule or not
    as_datalocal : bool
        Whether to save output files following PELE's DataLocal hierarchy or
        not
    conformation_path: str
        Path to the BCE server outupt to use to extract dihedral angles
    dihedral_mode: str
        Select what kind of dihedrals to extract (all or only flexible)
    """
    if charges_from_file is not None:
        charge_method_str = 'file\n' \
            + '   - Charge file: {}'.format(charges_from_file)
        charge_method = 'dummy'
    else:
        charge_method_str = charge_method

    log = Logger()
    log.info('-' * 60)
    log.info('Open Force Field parameterizer for PELE', peleffy.__version__)
    log.info('-' * 60)
    log.info(' - General:')
    log.info('   - Input PDB:', pdb_file)
    log.info('   - Output path:', output)
    log.info('   - Write solvent parameters:', with_solvent)
    log.info('   - DataLocal-like output:', as_datalocal)
    log.info(' - Parameterization:')
    log.info('   - Force field:', forcefield_name)
    log.info('   - Charge method:', charge_method_str)
    log.info(' - Rotamer library:')
    log.info('   - Resolution:', resolution)
    log.info('   - Exclude terminal rotamers:', exclude_terminal_rotamers)
    log.info('-' * 60)

    from peleffy.topology import Molecule, BCEConformations
    from peleffy.template import Impact
    from peleffy.solvent import OBC2
    from peleffy.forcefield import ForceFieldSelector
    from peleffy.topology import Topology
    from peleffy.utils import parse_charges_from_mae
    from peleffy.utils.input import PDBFile

    if not output:
        output = os.getcwd()

    # Initialize molecule
    if chain is not None:
        PDBreader = PDBFile(pdb_file)
        molecule = PDBreader.get_molecules_from_chain(
            selected_chain=chain,
            rotamer_resolution=resolution,
            exclude_terminal_rotamers=exclude_terminal_rotamers)
    else:
        molecule = Molecule(
            pdb_file,
            rotamer_resolution=resolution,
            exclude_terminal_rotamers=exclude_terminal_rotamers)

    # Initialize force field
    ff_selector = ForceFieldSelector()
    forcefield = ff_selector.get_by_name(forcefield_name)

    output_handler = OutputPathHandler(molecule,
                                       forcefield,
                                       output_path=output,
                                       as_datalocal=as_datalocal)

    # if conformation_path is set, we don't want a rotamer library
    if conformation_path is None:
        rotamer_library = peleffy.topology.RotamerLibrary(molecule)
        rotamer_library.to_file(output_handler.get_rotamer_library_path())

    # Parameterize molecule with the selected force field
    log.info(' - Parameterizing molecule')
    parameters = forcefield.parameterize(molecule, charge_method=charge_method)

    # Update charge parameters from the MAE file
    if charges_from_file is not None:
        parameters = parse_charges_from_mae(charges_from_file, parameters)

    # Generate the molecular topology
    topology = Topology(molecule, parameters)
    log.info(' - Parameters were built successfully:')
    log.info('   - {} atoms'.format(len(topology.atoms)))
    log.info('   - {} bonds'.format(len(topology.bonds)))
    log.info('   - {} torsions'.format(len(topology.angles)))
    log.info('   - {} propers'.format(len(topology.propers)))
    log.info('   - {} impropers'.format(len(topology.impropers)))

    # Generate the impact template
    impact = Impact(topology)
    impact.to_file(output_handler.get_impact_template_path())

    # Generate the solvent template
    if with_solvent:
        solvent = OBC2(topology)
        solvent.to_file(output_handler.get_solvent_template_path())

    if conformation_path is not None:
        conformations = BCEConformations(topology, conformation_path)
        conformations.calculate()
        conformations.save(output_handler.get_conformation_library_path())

    log.info(' - All files were generated successfully:')
    if conformation_path is None:
        log.info('   - {}'.format(output_handler.get_rotamer_library_path()))
    log.info('   - {}'.format(output_handler.get_impact_template_path()))
    if conformation_path is not None:
        log.info('   - {}'.format(
            output_handler.get_conformation_library_path()))
    if with_solvent:
        log.info('   - {}'.format(output_handler.get_solvent_template_path()))

    log.info('-' * 60)
Exemplo n.º 8
0
    def test_parameterizer(self):
        """It checks the parameterized method."""
        def check(hybridff, molecule, ffld_file, reference_file):
            """
            It checks the parameters obtained by the force field.

            Parameters
            ----------
            hybridff : an OpenFFOPLS2005ForceField object
                The hybrid force field to employ in the parameterization
                along with the ffld_file
            molecule : a peleffy.topology.Molecule
                The peleffy's Molecule object to parameterize with the
                ffld file
            ffld_file : str
                The path to the precomputed ffld file from where the
                parameters will be extracted
            reference_file : str
                The path to the file containing the reference parameters
            """
            parameters = parameterize_openffopls2005(hybridff, molecule,
                                                     ffld_file)

            writable_parameters = convert_all_quantities_to_string(parameters)

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

        from peleffy.topology import Molecule
        from peleffy.forcefield import OpenFFOPLS2005ForceField
        from peleffy.utils import (get_data_file_path,
                                   convert_all_quantities_to_string)
        from .utils import compare_dicts, parameterize_openffopls2005
        import json

        # Load molecule 1
        molecule = Molecule(get_data_file_path('ligands/methane.pdb'))
        hybridff = OpenFFOPLS2005ForceField(self.FORCE_FIELD_NAME)
        ffld_file = get_data_file_path('tests/MET_ffld_output.txt')

        # 1st check
        check(
            hybridff, molecule, ffld_file,
            get_data_file_path(
                'tests/MET_openff-1.2.1_opls2005_parameters1.json'))

        # 2nd check
        hybridff.set_nonbonding_parameters('OPLS2005')

        check(
            hybridff, molecule, ffld_file,
            get_data_file_path(
                'tests/MET_openff-1.2.1_opls2005_parameters2.json'))

        # 3rd check
        hybridff.set_nonbonding_parameters('OpenFF')
        hybridff.set_bond_parameters('OPLS2005')

        check(
            hybridff, molecule, ffld_file,
            get_data_file_path(
                'tests/MET_openff-1.2.1_opls2005_parameters3.json'))

        # 4th check
        hybridff.set_nonbonding_parameters('OpenFF')
        hybridff.set_bond_parameters('OpenFF')
        hybridff.set_angle_parameters('OPLS2005')

        check(
            hybridff, molecule, ffld_file,
            get_data_file_path(
                'tests/MET_openff-1.2.1_opls2005_parameters4.json'))

        # 5th check
        hybridff.set_nonbonding_parameters('OPLS2005')
        hybridff.set_bond_parameters('OPLS2005')
        hybridff.set_angle_parameters('OPLS2005')

        check(
            hybridff, molecule, ffld_file,
            get_data_file_path(
                'tests/MET_openff-1.2.1_opls2005_parameters5.json'))

        # Load molecule 2
        molecule = Molecule(get_data_file_path('ligands/ethylene.pdb'))
        hybridff = OpenFFOPLS2005ForceField(self.FORCE_FIELD_NAME)
        ffld_file = get_data_file_path('tests/ETL_ffld_output.txt')

        # 1st check
        check(
            hybridff, molecule, ffld_file,
            get_data_file_path(
                'tests/ETL_openff-1.2.1_opls2005_parameters1.json'))

        # 2nd check
        hybridff.set_nonbonding_parameters('OpenFF')
        hybridff.set_dihedral_parameters('OPLS2005')

        check(
            hybridff, molecule, ffld_file,
            get_data_file_path(
                'tests/ETL_openff-1.2.1_opls2005_parameters2.json'))
Exemplo n.º 9
0
    def test_atom_degrees(self):
        """It checks that the atom degree getter 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/methane.pdb')
        m = Molecule(pdb_path)
        degree_by_name = dict(zip(wrapper.get_atom_names(m),
                                  wrapper.get_atom_degrees(m)))

        assert degree_by_name == {' C1 ': 4, ' H1 ': 1, ' H2 ': 1,
                                  ' H3 ': 1, ' H4 ': 1}, \
            'Unexpected pairing between atom names and degrees'

        pdb_path = get_data_file_path('ligands/ethylene.pdb')
        m = Molecule(pdb_path)
        degree_by_name = dict(zip(wrapper.get_atom_names(m),
                                  wrapper.get_atom_degrees(m)))

        assert degree_by_name == {' C1 ': 3, ' C2 ': 3, ' H1 ': 1,
                                  ' H2 ': 1, ' H3 ': 1, ' H4 ': 1}, \
            'Unexpected pairing between atom names and degrees'

        pdb_path = get_data_file_path('ligands/acetylene.pdb')
        m = Molecule(pdb_path)
        degree_by_name = dict(zip(wrapper.get_atom_names(m),
                                  wrapper.get_atom_degrees(m)))

        assert degree_by_name == {' C1 ': 2, ' C2 ': 2, ' H1 ': 1,
                                  ' H2 ': 1}, \
            'Unexpected pairing between atom names and degrees'

        pdb_path = get_data_file_path('ligands/propionic_acid.pdb')
        m = Molecule(pdb_path)
        degree_by_name = dict(zip(wrapper.get_atom_names(m),
                                  wrapper.get_atom_degrees(m)))

        assert degree_by_name == {' C1 ': 4, ' C2 ': 4, ' C3 ': 3,
                                  ' O1 ': 1, ' O2 ': 2, ' H1 ': 1,
                                  ' H2 ': 1, ' H3 ': 1, ' H4 ': 1,
                                  ' H5 ': 1, ' H6 ': 1}, \
            'Unexpected pairing between atom names and degrees'

        pdb_path = get_data_file_path('ligands/trimethylglycine.pdb')
        m = Molecule(pdb_path)
        degree_by_name = dict(zip(wrapper.get_atom_names(m),
                                  wrapper.get_atom_degrees(m)))

        assert degree_by_name == {' C1 ': 4, ' N1 ': 4, ' C2 ': 4,
                                  ' C3 ': 4, ' C4 ': 4, ' C5 ': 3,
                                  ' O1 ': 1, ' O2 ': 1, ' H1 ': 1,
                                  ' H2 ': 1, ' H3 ': 1, ' H4 ': 1,
                                  ' H5 ': 1, ' H6 ': 1, ' H7 ': 1,
                                  ' H8 ': 1, ' H9 ': 1, ' H10': 1,
                                  ' H11': 1}, \
            'Unexpected pairing between atom names and degrees'

        pdb_path = get_data_file_path('ligands/malonate.pdb')
        m = Molecule(pdb_path)
        degree_by_name = dict(zip(wrapper.get_atom_names(m),
                                  wrapper.get_atom_degrees(m)))

        assert degree_by_name == {' O1 ': 1, ' C1 ': 3, ' O2 ': 1,
                                  ' C2 ': 4, ' C3 ': 3, ' O3 ': 2,
                                  ' O4 ': 1, ' H1 ': 1, ' H2 ': 1,
                                  ' H3 ': 1}, \
            'Unexpected pairing between atom names and degrees'