Ejemplo n.º 1
0
    def _execute(self, directory, available_resources):

        import mdtraj
        from openforcefield.topology import Molecule, Topology

        with open(self.force_field_path) as file:
            force_field_source = ForceFieldSource.parse_json(file.read())

        if not isinstance(force_field_source, SmirnoffForceFieldSource):

            raise ValueError(
                "Only SMIRNOFF force fields are supported by this protocol.", )

        # Load in the inputs
        force_field = force_field_source.to_force_field()

        trajectory = mdtraj.load_dcd(self.trajectory_file_path,
                                     self.coordinate_file_path)

        unique_molecules = []

        for component in self.substance.components:

            molecule = Molecule.from_smiles(smiles=component.smiles)
            unique_molecules.append(molecule)

        pdb_file = app.PDBFile(self.coordinate_file_path)
        topology = Topology.from_openmm(pdb_file.topology,
                                        unique_molecules=unique_molecules)

        # Compute the difference between the energies using the reduced force field,
        # and the full force field.
        energy_corrections = None

        if self.use_subset_of_force_field:

            target_system, _ = self._build_reduced_system(
                force_field, topology)

            subset_potentials_path = os.path.join(directory, f"subset.csv")
            subset_potentials = self._evaluate_reduced_potential(
                target_system, trajectory, subset_potentials_path,
                available_resources)

            full_statistics = StatisticsArray.from_pandas_csv(
                self.statistics_path)

            energy_corrections = (
                full_statistics[ObservableType.PotentialEnergy] -
                subset_potentials[ObservableType.PotentialEnergy])

        # Build the slightly perturbed system.
        reverse_system, reverse_parameter_value = self._build_reduced_system(
            force_field, topology, -self.perturbation_scale)

        forward_system, forward_parameter_value = self._build_reduced_system(
            force_field, topology, self.perturbation_scale)

        self.reverse_parameter_value = openmm_quantity_to_pint(
            reverse_parameter_value)
        self.forward_parameter_value = openmm_quantity_to_pint(
            forward_parameter_value)

        # Calculate the reduced potentials.
        self.reverse_potentials_path = os.path.join(directory, "reverse.csv")
        self.forward_potentials_path = os.path.join(directory, "forward.csv")

        self._evaluate_reduced_potential(
            reverse_system,
            trajectory,
            self.reverse_potentials_path,
            available_resources,
            energy_corrections,
        )
        self._evaluate_reduced_potential(
            forward_system,
            trajectory,
            self.forward_potentials_path,
            available_resources,
            energy_corrections,
        )
Ejemplo n.º 2
0
molAPO = PDBFile(f'{PDB_DIR}/{SEED_PDB}.fab.fixed.pdb')
molLIG = PDBFile(f'{PDB_DIR}/{TARGET_CID}.pdb')
molSMI = Chem.MolToSmiles(
    molPROBE, isomericSmiles=True, allBondsExplicit=True)

model = Modeller(molAPO.topology, molAPO.getPositions())
model.add(molLIG.topology, molLIG.getPositions())

with open('holo.pdb', 'w+') as outfile:
    PDBFile.writeFile(model.topology, model.getPositions(), outfile)

""" Parameterize the holo-complex """
GAFFForceField = GAFFTemplateGenerator.INSTALLED_FORCEFIELDS[-1]
GAFFTemplate = GAFFTemplateGenerator(forcefield=GAFFForceField)
GAFFTemplate.add_molecules(
    Molecule.from_smiles(molSMI, allow_undefined_stereo=True))
forcefield = app.ForceField('amber14/protein.ff14SB.xml')
forcefield.registerTemplateGenerator(GAFFTemplate.generator)
system00 = forcefield.createSystem(model.topology)

""" Minimize the holo-complex """
holo = app.PDBFile('holo.pdb')

integrator = LangevinIntegrator(
    LANGE_TEMPERATURE, LANGE_FRICTION, LANGE_STEPSIZE)
integrator.setConstraintTolerance(LANGE_TOLERANCE)

simulation = Simulation(holo.topology, system00, integrator)
simulation.context.setPositions(holo.getPositions())
simulation.minimizeEnergy(ENERGY_TOLERANCE, MAX_ENERGY_ITERS)
Ejemplo n.º 3
0
def _generate_residue_name(residue, smiles):
    """Generates residue name for a particular residue which
    corresponds to a particular smiles pattern.

    Where possible (i.e for amino acids and ions) a standard residue
    name will be returned, otherwise a random name will be used.

    Parameters
    ----------
    residue: mdtraj.core.topology.Residue
        The residue to assign the name to.
    smiles: str
        The SMILES pattern to generate a resiude name for.
    """
    from mdtraj.core import residue_names
    from openforcefield.topology import Molecule

    # Define the set of residue names which should be discarded
    # if randomly generated as they have a reserved meaning.
    # noinspection PyProtectedMember
    forbidden_residue_names = [
        *residue_names._AMINO_ACID_CODES,
        *residue_names._SOLVENT_TYPES,
        *residue_names._WATER_RESIDUES,
        "ADE",
        "CYT",
        "CYX",
        "DAD",
        "DGU",
        "FOR",
        "GUA",
        "HID",
        "HIE",
        "HIH",
        "HSD",
        "HSH",
        "HSP",
        "NMA",
        "THY",
        "URA",
    ]

    amino_residue_mappings = {
        "C[C@H](N)C(=O)O": "ALA",
        "N=C(N)NCCC[C@H](N)C(=O)O": "ARG",
        "NC(=O)C[C@H](N)C(=O)O": "ASN",
        "N[C@@H](CC(=O)O)C(=O)O": "ASP",
        "N[C@@H](CS)C(=O)O": "CYS",
        "N[C@@H](CCC(=O)O)C(=O)O": "GLU",
        "NC(=O)CC[C@H](N)C(=O)O": "GLN",
        "NCC(=O)O": "GLY",
        "N[C@@H](Cc1c[nH]cn1)C(=O)O": "HIS",
        "CC[C@H](C)[C@H](N)C(=O)O": "ILE",
        "CC(C)C[C@H](N)C(=O)O": "LEU",
        "NCCCC[C@H](N)C(=O)O": "LYS",
        "CSCC[C@H](N)C(=O)O": "MET",
        "N[C@@H](Cc1ccccc1)C(=O)O": "PHE",
        "O=C(O)[C@@H]1CCCN1": "PRO",
        "N[C@@H](CO)C(=O)O": "SER",
        "C[C@@H](O)[C@H](N)C(=O)O": "THR",
        "N[C@@H](Cc1c[nH]c2ccccc12)C(=O)O": "TRP",
        "N[C@@H](Cc1ccc(O)cc1)C(=O)O": "TYR",
        "CC(C)[C@H](N)C(=O)O": "VAL",
    }

    standardized_smiles = Component(smiles=smiles).smiles

    # Check for amino acids.
    if standardized_smiles in amino_residue_mappings:
        residue.name = amino_residue_mappings[standardized_smiles]
        return

    # Check for water
    if standardized_smiles == "O":

        residue.name = "HOH"

        # Re-assign the water atom names. These need to be set to get
        # correct CONECT statements.
        h_counter = 1

        for atom in residue.atoms:

            if atom.element.symbol == "O":
                atom.name = "O1"
            else:
                atom.name = f"H{h_counter}"
                h_counter += 1

        return

    # Check for ions
    openff_molecule = Molecule.from_smiles(smiles, allow_undefined_stereo=True)

    if openff_molecule.n_atoms == 1:
        residue.name = _ion_residue_name(openff_molecule)
        residue.atom(0).name = residue.name

        return

    # Randomly generate a name
    random_residue_name = "".join(
        [random.choice(string.ascii_uppercase) for _ in range(3)])

    while random_residue_name in forbidden_residue_names:
        # Re-choose the residue name until we find a safe one.
        random_residue_name = "".join(
            [random.choice(string.ascii_uppercase) for _ in range(3)])

    residue.name = random_residue_name

    # Assign unique atom names.
    element_counter = defaultdict(int)

    for atom in residue.atoms:
        atom.name = f"{atom.element.symbol}{element_counter[atom.element.symbol] + 1}"
        element_counter[atom.element.symbol] += 1
Ejemplo n.º 4
0
    def _execute(self, directory, available_resources):

        from openforcefield.topology import Molecule, Topology

        force_field_source = ForceFieldSource.from_json(self.force_field_path)
        cutoff = pint_quantity_to_openmm(force_field_source.cutoff)

        # Load in the systems topology
        openmm_pdb_file = app.PDBFile(self.coordinate_file_path)

        # Create an OFF topology for better insight into the layout of the system
        # topology.
        unique_molecules = {}

        for component in self.substance:
            unique_molecule = Molecule.from_smiles(component.smiles)
            unique_molecules[unique_molecule.to_smiles()] = unique_molecule

        # Parameterize each component in the system.
        system_templates = {}

        for index, (smiles,
                    unique_molecule) in enumerate(unique_molecules.items()):

            if smiles in ["O", "[H]O[H]", "[H][O][H]"]:

                component_system = self._build_tip3p_system(
                    cutoff,
                    openmm_pdb_file.topology.getUnitCellDimensions(),
                )

            else:

                component_directory = os.path.join(directory, str(index))
                os.makedirs(component_directory, exist_ok=True)

                with temporarily_change_directory(component_directory):

                    component_system = self._parameterize_molecule(
                        unique_molecule, force_field_source, cutoff)

            system_templates[smiles] = component_system

        # Apply the parameters to the topology.
        topology = Topology.from_openmm(openmm_pdb_file.topology,
                                        unique_molecules.values())

        # Create the full system object from the component templates.
        system = self._create_empty_system(cutoff)

        for topology_molecule in topology.topology_molecules:

            smiles = topology_molecule.reference_molecule.to_smiles()
            system_template = system_templates[smiles]

            index_map = {}

            for index, topology_atom in enumerate(topology_molecule.atoms):
                index_map[topology_atom.atom.molecule_particle_index] = index

            # Append the component template to the full system.
            self._append_system(system, system_template, index_map)

        if openmm_pdb_file.topology.getPeriodicBoxVectors() is not None:

            system.setDefaultPeriodicBoxVectors(
                *openmm_pdb_file.topology.getPeriodicBoxVectors())

        # Serialize the system object.
        self.system_path = os.path.join(directory, "system.xml")

        with open(self.system_path, "w") as file:
            file.write(openmm.XmlSerializer.serialize(system))